Re: (EXT) [PATCH 5/6] dt-bindings: drm/bridge: ti-sn65dsi83: Add reset controller documentation

2022-05-31 Thread Alexander Stein
Hi Marco,

Am Montag, 30. Mai 2022, 17:05:48 CEST schrieb Marco Felsch:
> The bridge device can now also be enabled/disabled by an external reset
> controller. So the device now supports either enable/disable by simple
> GPIO or by an Reset-Controller.
> 
> Signed-off-by: Marco Felsch 
> ---
>  .../devicetree/bindings/display/bridge/ti,sn65dsi83.yaml| 6 ++
>  1 file changed, 6 insertions(+)
> 
> diff --git
> a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml
> b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml index
> 7306b9874dc3..eff8360c184e 100644
> --- a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml
> +++ b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml
> @@ -35,6 +35,12 @@ properties:
>vcc-supply:
>  description: A 1.8V power supply (see regulator/regulator.yaml).
> 
> +  resets:
> +maxItems: 1
> +description: |
> +  Reset specifier for bridge_en pin. This is required only if the
> brdige_en +  pin is connected to a reset controller.
> +
>ports:
>  $ref: /schemas/graph.yaml#/properties/ports

Maybe it should be added here, that 'resets' is an alternative to 'enable-
gpios' as both are essentially controlling the same pin from the bridge.

Best regards
Alexander




[syzbot] WARNING in dma_map_sgtable (2)

2022-05-31 Thread syzbot
Hello,

syzbot found the following issue on:

HEAD commit:7e062cda7d90 Merge tag 'net-next-5.19' of git://git.kernel..
git tree:   upstream
console+strace: https://syzkaller.appspot.com/x/log.txt?x=172151d3f0
kernel config:  https://syzkaller.appspot.com/x/.config?x=e9d71d3c07c36588
dashboard link: https://syzkaller.appspot.com/bug?extid=3ba551855046ba3b3806
compiler:   Debian clang version 
13.0.1-++20220126092033+75e33f71c2da-1~exp1~20220126212112.63, GNU ld (GNU 
Binutils for Debian) 2.35.2
syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=12918503f0
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=1386fa39f0

Bisection is inconclusive: the issue happens on the oldest tested release.

bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=14107ee5f0
final oops: https://syzkaller.appspot.com/x/report.txt?x=16107ee5f0
console output: https://syzkaller.appspot.com/x/log.txt?x=12107ee5f0

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+3ba551855046ba3b3...@syzkaller.appspotmail.com

[ cut here ]
WARNING: CPU: 0 PID: 3610 at kernel/dma/mapping.c:188 
dma_map_sgtable+0x203/0x260 kernel/dma/mapping.c:264
Modules linked in:
CPU: 0 PID: 3610 Comm: syz-executor162 Not tainted 
5.18.0-syzkaller-04943-g7e062cda7d90 #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 
01/01/2011
RIP: 0010:__dma_map_sg_attrs kernel/dma/mapping.c:188 [inline]
RIP: 0010:dma_map_sgtable+0x203/0x260 kernel/dma/mapping.c:264
Code: 75 15 e8 50 5f 14 00 eb cb e8 49 5f 14 00 eb c4 e8 42 5f 14 00 eb bd e8 
3b 5f 14 00 0f 0b bd fb ff ff ff eb af e8 2d 5f 14 00 <0f> 0b 31 ed 48 bb 00 00 
00 00 00 fc ff df e9 7b ff ff ff 89 e9 80
RSP: 0018:c9000305fd40 EFLAGS: 00010293
RAX: 81723873 RBX: dc00 RCX: 88801fbb8000
RDX:  RSI: 0001 RDI: 0002
RBP: 8881487e5408 R08: 81723743 R09: ed1003592c9e
R10: ed1003592c9e R11: 111003592c9c R12: 8881487e5000
R13: 88801ac964e0 R14:  R15: 0001
FS:  56c2a300() GS:8880b9a0() knlGS:
CS:  0010 DS:  ES:  CR0: 80050033
CR2: 005d84c8 CR3: 1f1ef000 CR4: 003506f0
DR0:  DR1:  DR2: 
DR3:  DR6: fffe0ff0 DR7: 0400
Call Trace:
 
 get_sg_table+0xf9/0x150 drivers/dma-buf/udmabuf.c:72
 begin_cpu_udmabuf+0xf5/0x160 drivers/dma-buf/udmabuf.c:126
 dma_buf_begin_cpu_access+0xd8/0x170 drivers/dma-buf/dma-buf.c:1172
 dma_buf_ioctl+0x2a0/0x2f0 drivers/dma-buf/dma-buf.c:363
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:870 [inline]
 __se_sys_ioctl+0xfb/0x170 fs/ioctl.c:856
 do_syscall_x64 arch/x86/entry/common.c:50 [inline]
 do_syscall_64+0x2b/0x70 arch/x86/entry/common.c:80
 entry_SYSCALL_64_after_hwframe+0x46/0xb0
RIP: 0033:0x7f8bf9c6dc19
Code: 28 c3 e8 2a 14 00 00 66 2e 0f 1f 84 00 00 00 00 00 48 89 f8 48 89 f7 48 
89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 
c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:7ffd7cfae1d8 EFLAGS: 0246 ORIG_RAX: 0010
RAX: ffda RBX:  RCX: 7f8bf9c6dc19
RDX: 2100 RSI: 40086200 RDI: 0006
RBP: 7f8bf9c31dc0 R08:  R09: 
R10:  R11: 0246 R12: 7f8bf9c31e50
R13:  R14:  R15: 
 


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkal...@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
For information about bisection process see: https://goo.gl/tpsmEJ#bisection
syzbot can test patches for this issue, for details see:
https://goo.gl/tpsmEJ#testing-patches


[PATCH 2/7] dt-bindings: display: mediatek: dpi: add binding for MT8365

2022-05-31 Thread Fabien Parent
DPI for MT8365 is compatible with MT8192 but requires an additional
clock. Modify the documentation to requires this clock only on MT8365 SoCs.

Signed-off-by: Fabien Parent 
---
 .../display/mediatek/mediatek,dpi.yaml| 44 ---
 1 file changed, 37 insertions(+), 7 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml 
b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
index caf4c88708f4..c9c9f4d5ebe7 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
@@ -17,13 +17,18 @@ description: |
 
 properties:
   compatible:
-enum:
-  - mediatek,mt2701-dpi
-  - mediatek,mt7623-dpi
-  - mediatek,mt8173-dpi
-  - mediatek,mt8183-dpi
-  - mediatek,mt8186-dpi
-  - mediatek,mt8192-dpi
+oneOf:
+  - enum:
+  - mediatek,mt2701-dpi
+  - mediatek,mt7623-dpi
+  - mediatek,mt8173-dpi
+  - mediatek,mt8183-dpi
+  - mediatek,mt8186-dpi
+  - mediatek,mt8192-dpi
+  - items:
+  - enum:
+  - mediatek,mt8365-dpi
+  - const: mediatek,mt8192-dpi
 
   reg:
 maxItems: 1
@@ -32,16 +37,20 @@ properties:
 maxItems: 1
 
   clocks:
+minItems: 3
 items:
   - description: Pixel Clock
   - description: Engine Clock
   - description: DPI PLL
+  - description: DPI Clock
 
   clock-names:
+minItems: 3
 items:
   - const: pixel
   - const: engine
   - const: pll
+  - const: dpi
 
   pinctrl-0: true
   pinctrl-1: true
@@ -71,6 +80,27 @@ required:
 
 additionalProperties: false
 
+allOf:
+  - if:
+  properties:
+compatible:
+  contains:
+const: mediatek,mt8365-dpi
+
+then:
+  properties:
+clocks:
+  maxItems: 4
+clock-names:
+  maxItems: 4
+
+else:
+  properties:
+clocks:
+  maxItems: 3
+clock-names:
+  maxItems: 3
+
 examples:
   - |
 #include 
-- 
2.36.1



[PATCH 4/7] soc: mediatek: mutex: add MT8365 support

2022-05-31 Thread Fabien Parent
Add mutex support for MT8365 SoC.

Signed-off-by: Fabien Parent 
---
 drivers/soc/mediatek/mtk-mutex.c | 40 
 1 file changed, 40 insertions(+)

diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index 981d56967e7a..b8d5c4a62542 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -110,6 +110,20 @@
 #define MT8195_MUTEX_MOD_DISP_DP_INTF0 21
 #define MT8195_MUTEX_MOD_DISP_PWM0 27
 
+#define MT8365_MUTEX_MOD_DISP_OVL0 7
+#define MT8365_MUTEX_MOD_DISP_OVL0_2L  8
+#define MT8365_MUTEX_MOD_DISP_RDMA09
+#define MT8365_MUTEX_MOD_DISP_RDMA110
+#define MT8365_MUTEX_MOD_DISP_WDMA011
+#define MT8365_MUTEX_MOD_DISP_COLOR0   12
+#define MT8365_MUTEX_MOD_DISP_CCORR13
+#define MT8365_MUTEX_MOD_DISP_AAL  14
+#define MT8365_MUTEX_MOD_DISP_GAMMA15
+#define MT8365_MUTEX_MOD_DISP_DITHER   16
+#define MT8365_MUTEX_MOD_DISP_DSI0 17
+#define MT8365_MUTEX_MOD_DISP_PWM0 20
+#define MT8365_MUTEX_MOD_DISP_DPI0 22
+
 #define MT2712_MUTEX_MOD_DISP_PWM2 10
 #define MT2712_MUTEX_MOD_DISP_OVL0 11
 #define MT2712_MUTEX_MOD_DISP_OVL1 12
@@ -315,6 +329,22 @@ static const unsigned int 
mt8195_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_DP_INTF0] = MT8195_MUTEX_MOD_DISP_DP_INTF0,
 };
 
+static const unsigned int mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+   [DDP_COMPONENT_AAL0] = MT8365_MUTEX_MOD_DISP_AAL,
+   [DDP_COMPONENT_CCORR] = MT8365_MUTEX_MOD_DISP_CCORR,
+   [DDP_COMPONENT_COLOR0] = MT8365_MUTEX_MOD_DISP_COLOR0,
+   [DDP_COMPONENT_DITHER] = MT8365_MUTEX_MOD_DISP_DITHER,
+   [DDP_COMPONENT_DPI0] = MT8365_MUTEX_MOD_DISP_DPI0,
+   [DDP_COMPONENT_DSI0] = MT8365_MUTEX_MOD_DISP_DSI0,
+   [DDP_COMPONENT_GAMMA] = MT8365_MUTEX_MOD_DISP_GAMMA,
+   [DDP_COMPONENT_OVL0] = MT8365_MUTEX_MOD_DISP_OVL0,
+   [DDP_COMPONENT_OVL_2L0] = MT8365_MUTEX_MOD_DISP_OVL0_2L,
+   [DDP_COMPONENT_PWM0] = MT8365_MUTEX_MOD_DISP_PWM0,
+   [DDP_COMPONENT_RDMA0] = MT8365_MUTEX_MOD_DISP_RDMA0,
+   [DDP_COMPONENT_RDMA1] = MT8365_MUTEX_MOD_DISP_RDMA1,
+   [DDP_COMPONENT_WDMA0] = MT8365_MUTEX_MOD_DISP_WDMA0,
+};
+
 static const unsigned int mt2712_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
@@ -423,6 +453,14 @@ static const struct mtk_mutex_data 
mt8195_mutex_driver_data = {
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
 };
 
+static const struct mtk_mutex_data mt8365_mutex_driver_data = {
+   .mutex_mod = mt8365_mutex_mod,
+   .mutex_sof = mt8183_mutex_sof,
+   .mutex_mod_reg = MT8183_MUTEX0_MOD0,
+   .mutex_sof_reg = MT8183_MUTEX0_SOF0,
+   .no_clk = true,
+};
+
 struct mtk_mutex *mtk_mutex_get(struct device *dev)
 {
struct mtk_mutex_ctx *mtx = dev_get_drvdata(dev);
@@ -665,6 +703,8 @@ static const struct of_device_id mutex_driver_dt_match[] = {
  .data = &mt8192_mutex_driver_data},
{ .compatible = "mediatek,mt8195-disp-mutex",
  .data = &mt8195_mutex_driver_data},
+   { .compatible = "mediatek,mt8365-disp-mutex",
+ .data = &mt8365_mutex_driver_data},
{},
 };
 MODULE_DEVICE_TABLE(of, mutex_driver_dt_match);
-- 
2.36.1



[PATCH 5/7] soc: mediatek: mt8365-mmsys: add DPI/HDMI display path

2022-05-31 Thread Fabien Parent
Right now only the DSI path connections are described in the mt8365
mmsys driver. The external path will be DPI/HDMI. This commit adds
the connections for DPI/HDMI.

Signed-off-by: Fabien Parent 
---
 drivers/soc/mediatek/mt8365-mmsys.h | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/soc/mediatek/mt8365-mmsys.h 
b/drivers/soc/mediatek/mt8365-mmsys.h
index 24129a6c25f8..7abaf048d91e 100644
--- a/drivers/soc/mediatek/mt8365-mmsys.h
+++ b/drivers/soc/mediatek/mt8365-mmsys.h
@@ -10,6 +10,9 @@
 #define MT8365_DISP_REG_CONFIG_DISP_RDMA0_RSZ0_SEL_IN  0xf60
 #define MT8365_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN  0xf64
 #define MT8365_DISP_REG_CONFIG_DISP_DSI0_SEL_IN0xf68
+#define MT8365_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL 0xfd0
+#define MT8365_DISP_REG_CONFIG_DISP_DPI0_SEL_IN0xfd8
+#define MT8365_DISP_REG_CONFIG_DISP_LVDS_SYS_CFG_000xfdc
 
 #define MT8365_RDMA0_SOUT_COLOR0   0x1
 #define MT8365_DITHER_MOUT_EN_DSI0 0x1
@@ -18,6 +21,10 @@
 #define MT8365_RDMA0_RSZ0_SEL_IN_RDMA0 0x0
 #define MT8365_DISP_COLOR_SEL_IN_COLOR00x0
 #define MT8365_OVL0_MOUT_PATH0_SEL BIT(0)
+#define MT8365_RDMA1_SOUT_DPI0 0x1
+#define MT8365_DPI0_SEL_IN_RDMA1   0x0
+#define MT8365_LVDS_SYS_CFG_00_SEL_LVDS_PXL_CLK0x1
+#define MT8365_DPI0_SEL_IN_RDMA1   0x0
 
 static const struct mtk_mmsys_routes mt8365_mmsys_routing_table[] = {
{
@@ -55,6 +62,21 @@ static const struct mtk_mmsys_routes 
mt8365_mmsys_routing_table[] = {
MT8365_DISP_REG_CONFIG_DISP_RDMA0_RSZ0_SEL_IN,
MT8365_RDMA0_RSZ0_SEL_IN_RDMA0, MT8365_RDMA0_RSZ0_SEL_IN_RDMA0
},
+   {
+   DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
+   MT8365_DISP_REG_CONFIG_DISP_LVDS_SYS_CFG_00,
+   MT8365_LVDS_SYS_CFG_00_SEL_LVDS_PXL_CLK, 
MT8365_LVDS_SYS_CFG_00_SEL_LVDS_PXL_CLK
+   },
+   {
+   DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
+   MT8365_DISP_REG_CONFIG_DISP_DPI0_SEL_IN,
+   MT8365_DPI0_SEL_IN_RDMA1, MT8365_DPI0_SEL_IN_RDMA1
+   },
+   {
+   DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
+   MT8365_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL,
+   MT8365_RDMA1_SOUT_DPI0, MT8365_RDMA1_SOUT_DPI0
+   },
 };
 
 #endif /* __SOC_MEDIATEK_MT8365_MMSYS_H */
-- 
2.36.1



[PATCH 7/7] drm/mediatek: add MT8365 SoC support

2022-05-31 Thread Fabien Parent
Add DRM support for MT8365 SoC.

Signed-off-by: Fabien Parent 
---
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 27 ++
 1 file changed, 27 insertions(+)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c 
b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 6abe6bcacbdc..0a30ec75b1e2 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -195,6 +195,22 @@ static const enum mtk_ddp_comp_id mt8192_mtk_ddp_ext[] = {
DDP_COMPONENT_DPI0,
 };
 
+static const enum mtk_ddp_comp_id mt8365_mtk_ddp_main[] = {
+   DDP_COMPONENT_OVL0,
+   DDP_COMPONENT_RDMA0,
+   DDP_COMPONENT_COLOR0,
+   DDP_COMPONENT_CCORR,
+   DDP_COMPONENT_AAL0,
+   DDP_COMPONENT_GAMMA,
+   DDP_COMPONENT_DITHER,
+   DDP_COMPONENT_DSI0,
+};
+
+static const enum mtk_ddp_comp_id mt8365_mtk_ddp_ext[] = {
+   DDP_COMPONENT_RDMA1,
+   DDP_COMPONENT_DPI0,
+};
+
 static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
.main_path = mt2701_mtk_ddp_main,
.main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
@@ -253,6 +269,13 @@ static const struct mtk_mmsys_driver_data 
mt8192_mmsys_driver_data = {
.ext_len = ARRAY_SIZE(mt8192_mtk_ddp_ext),
 };
 
+static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
+   .main_path = mt8365_mtk_ddp_main,
+   .main_len = ARRAY_SIZE(mt8365_mtk_ddp_main),
+   .ext_path = mt8365_mtk_ddp_ext,
+   .ext_len = ARRAY_SIZE(mt8365_mtk_ddp_ext),
+};
+
 static int mtk_drm_kms_init(struct drm_device *drm)
 {
struct mtk_drm_private *private = drm->dev_private;
@@ -490,6 +513,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
  .data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8192-disp-mutex",
  .data = (void *)MTK_DISP_MUTEX },
+   { .compatible = "mediatek,mt8365-disp-mutex",
+ .data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8173-disp-od",
  .data = (void *)MTK_DISP_OD },
{ .compatible = "mediatek,mt2701-disp-ovl",
@@ -564,6 +589,8 @@ static const struct of_device_id mtk_drm_of_ids[] = {
  .data = &mt8186_mmsys_driver_data},
{ .compatible = "mediatek,mt8192-mmsys",
  .data = &mt8192_mmsys_driver_data},
+   { .compatible = "mediatek,mt8365-mmsys",
+ .data = &mt8365_mmsys_driver_data},
{ }
 };
 MODULE_DEVICE_TABLE(of, mtk_drm_of_ids);
-- 
2.36.1



[PATCH] drm/mediatek: fix crtc index computation

2022-05-31 Thread Fabien Parent
The code always assume that the main path is enabled, which is not
always the case. When the main path is not enabled, the CRTC index
of the ext path is incorrect which makes the secondary path
not usable. Fix the CRTC index calculation.

Signed-off-by: Fabien Parent 
---
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 46 +++--
 1 file changed, 34 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c 
b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 5d7504a72b11..6f2abfc608fb 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -430,25 +430,47 @@ int mtk_ddp_comp_get_id(struct device_node *node,
return -EINVAL;
 }
 
+static bool mtk_drm_comp_is_enabled(struct drm_device *drm,
+   const enum mtk_ddp_comp_id *path,
+   unsigned int path_len)
+{
+   struct mtk_drm_private *priv = drm->dev_private;
+
+   return path && path_len && !!priv->comp_node[path[path_len - 1]];
+}
+
 unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm,
struct device *dev)
 {
struct mtk_drm_private *private = drm->dev_private;
-   unsigned int ret = 0;
+   unsigned int index = 0;
 
-   if (mtk_drm_find_comp_in_ddp(dev, private->data->main_path, 
private->data->main_len,
+   if (mtk_drm_find_comp_in_ddp(dev, private->data->main_path,
+private->data->main_len,
 private->ddp_comp))
-   ret = BIT(0);
-   else if (mtk_drm_find_comp_in_ddp(dev, private->data->ext_path,
- private->data->ext_len, 
private->ddp_comp))
-   ret = BIT(1);
-   else if (mtk_drm_find_comp_in_ddp(dev, private->data->third_path,
- private->data->third_len, 
private->ddp_comp))
-   ret = BIT(2);
-   else
-   DRM_INFO("Failed to find comp in ddp table\n");
+   return BIT(index);
+
+   if (mtk_drm_comp_is_enabled(drm, private->data->main_path,
+   private->data->main_len))
+   index++;
 
-   return ret;
+   if (mtk_drm_find_comp_in_ddp(dev, private->data->ext_path,
+private->data->ext_len,
+private->ddp_comp))
+   return BIT(index);
+
+   if (mtk_drm_comp_is_enabled(drm, private->data->ext_path,
+   private->data->ext_len))
+   index++;
+
+   if (mtk_drm_find_comp_in_ddp(dev, private->data->third_path,
+ private->data->third_len,
+ private->ddp_comp))
+   return BIT(index);
+
+   DRM_INFO("Failed to find comp in ddp table\n");
+
+   return 0;
 }
 
 int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
-- 
2.36.1



[PATCH 1/7] dt-bindings: display: mediatek: dpi: add power-domains property

2022-05-31 Thread Fabien Parent
DPI is part of the display / multimedia block in MediaTek SoCs, and
always have a power-domain (at least in the upstream device-trees).
Add the power-domains property to the binding documentation.

Signed-off-by: Fabien Parent 
---
 .../devicetree/bindings/display/mediatek/mediatek,dpi.yaml  | 6 ++
 1 file changed, 6 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml 
b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
index 77ee1b923991..caf4c88708f4 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
@@ -57,6 +57,9 @@ properties:
   Output port node. This port should be connected to the input port of an
   attached HDMI or LVDS encoder chip.
 
+  power-domains:
+maxItems: 1
+
 required:
   - compatible
   - reg
@@ -64,6 +67,7 @@ required:
   - clocks
   - clock-names
   - port
+  - power-domains
 
 additionalProperties: false
 
@@ -71,11 +75,13 @@ examples:
   - |
 #include 
 #include 
+#include 
 
 dpi0: dpi@1401d000 {
 compatible = "mediatek,mt8173-dpi";
 reg = <0x1401d000 0x1000>;
 interrupts = ;
+power-domains = <&spm MT8173_POWER_DOMAIN_MM>;
 clocks = <&mmsys CLK_MM_DPI_PIXEL>,
  <&mmsys CLK_MM_DPI_ENGINE>,
  <&apmixedsys CLK_APMIXED_TVDPLL>;
-- 
2.36.1



[PATCH 3/7] dt-bindings: display: mediatek: add bindings for MT8365 SoC

2022-05-31 Thread Fabien Parent
Add MT8365 binding documentation for all the display components that are
compatible with the compatible string from other SoCs.

Signed-off-by: Fabien Parent 
---
 .../bindings/display/mediatek/mediatek,aal.yaml |  1 +
 .../display/mediatek/mediatek,ccorr.yaml|  1 +
 .../display/mediatek/mediatek,color.yaml|  1 +
 .../display/mediatek/mediatek,dither.yaml   |  1 +
 .../bindings/display/mediatek/mediatek,dsi.yaml | 17 +++--
 .../display/mediatek/mediatek,gamma.yaml|  1 +
 .../display/mediatek/mediatek,mutex.yaml|  1 +
 .../bindings/display/mediatek/mediatek,ovl.yaml |  1 +
 .../display/mediatek/mediatek,rdma.yaml |  1 +
 9 files changed, 19 insertions(+), 6 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/mediatek/mediatek,aal.yaml 
b/Documentation/devicetree/bindings/display/mediatek/mediatek,aal.yaml
index d4d585485e7b..d47bc72f09c0 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,aal.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,aal.yaml
@@ -33,6 +33,7 @@ properties:
   - mediatek,mt8186-disp-aal
   - mediatek,mt8192-disp-aal
   - mediatek,mt8195-disp-aal
+  - mediatek,mt8365-disp-aal
   - const: mediatek,mt8183-disp-aal
 
   reg:
diff --git 
a/Documentation/devicetree/bindings/display/mediatek/mediatek,ccorr.yaml 
b/Documentation/devicetree/bindings/display/mediatek/mediatek,ccorr.yaml
index 63fb02014a56..fc999e614718 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,ccorr.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,ccorr.yaml
@@ -32,6 +32,7 @@ properties:
   - items:
   - enum:
   - mediatek,mt8186-disp-ccorr
+  - mediatek,mt8365-disp-ccorr
   - const: mediatek,mt8183-disp-ccorr
 
   reg:
diff --git 
a/Documentation/devicetree/bindings/display/mediatek/mediatek,color.yaml 
b/Documentation/devicetree/bindings/display/mediatek/mediatek,color.yaml
index d2f89ee7996f..9d081da433e8 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,color.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,color.yaml
@@ -39,6 +39,7 @@ properties:
   - mediatek,mt8186-disp-color
   - mediatek,mt8192-disp-color
   - mediatek,mt8195-disp-color
+  - mediatek,mt8365-disp-color
   - const: mediatek,mt8173-disp-color
   reg:
 maxItems: 1
diff --git 
a/Documentation/devicetree/bindings/display/mediatek/mediatek,dither.yaml 
b/Documentation/devicetree/bindings/display/mediatek/mediatek,dither.yaml
index 8ad8187c02d1..a7706cd65675 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dither.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dither.yaml
@@ -29,6 +29,7 @@ properties:
   - mediatek,mt8186-disp-dither
   - mediatek,mt8192-disp-dither
   - mediatek,mt8195-disp-dither
+  - mediatek,mt8365-disp-dither
   - const: mediatek,mt8183-disp-dither
 
   reg:
diff --git 
a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml 
b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml
index fa5bdf28668a..d17ea215960c 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml
@@ -22,12 +22,17 @@ allOf:
 
 properties:
   compatible:
-enum:
-  - mediatek,mt2701-dsi
-  - mediatek,mt7623-dsi
-  - mediatek,mt8167-dsi
-  - mediatek,mt8173-dsi
-  - mediatek,mt8183-dsi
+oneOf:
+  - enum:
+  - mediatek,mt2701-dsi
+  - mediatek,mt7623-dsi
+  - mediatek,mt8167-dsi
+  - mediatek,mt8173-dsi
+  - mediatek,mt8183-dsi
+  - items:
+  - enum:
+  - mediatek,mt8365-dsi
+  - const: mediatek,mt8183-dsi
 
   reg:
 maxItems: 1
diff --git 
a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml 
b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml
index a89ea0ea7542..f54859cfc97b 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml
@@ -30,6 +30,7 @@ properties:
   - mediatek,mt8186-disp-gamma
   - mediatek,mt8192-disp-gamma
   - mediatek,mt8195-disp-gamma
+  - mediatek,mt8365-disp-gamma
   - const: mediatek,mt8183-disp-gamma
 
   reg:
diff --git 
a/Documentation/devicetree/bindings/display/mediatek/mediatek,mutex.yaml 
b/Documentation/devicetree/bindings/display/mediatek/mediatek,mutex.yaml
index 3fdad71210b4..f4a12dfae77b 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,mutex.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,

[PATCH 6/7] drm/mediatek: dpi: add support for dpi clock

2022-05-31 Thread Fabien Parent
MT8365 requires an additional clock for DPI. Add support for that
additional clock.

Signed-off-by: Fabien Parent 
---
 drivers/gpu/drm/mediatek/mtk_dpi.c | 18 +-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c 
b/drivers/gpu/drm/mediatek/mtk_dpi.c
index e61cd67b978f..7872db60840e 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -72,6 +72,7 @@ struct mtk_dpi {
struct device *dev;
struct clk *engine_clk;
struct clk *pixel_clk;
+   struct clk *dpi_clk;
struct clk *tvd_clk;
int irq;
struct drm_display_mode mode;
@@ -412,6 +413,7 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi)
mtk_dpi_disable(dpi);
clk_disable_unprepare(dpi->pixel_clk);
clk_disable_unprepare(dpi->engine_clk);
+   clk_disable_unprepare(dpi->dpi_clk);
 }
 
 static int mtk_dpi_power_on(struct mtk_dpi *dpi)
@@ -421,10 +423,16 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
if (++dpi->refcount != 1)
return 0;
 
+   ret = clk_prepare_enable(dpi->dpi_clk);
+   if (ret) {
+   dev_err(dpi->dev, "failed to enable dpi clock: %d\n", ret);
+   goto err_refcount;
+   }
+
ret = clk_prepare_enable(dpi->engine_clk);
if (ret) {
dev_err(dpi->dev, "Failed to enable engine clock: %d\n", ret);
-   goto err_refcount;
+   goto err_engine;
}
 
ret = clk_prepare_enable(dpi->pixel_clk);
@@ -441,6 +449,8 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
 
 err_pixel:
clk_disable_unprepare(dpi->engine_clk);
+err_engine:
+   clk_disable_unprepare(dpi->dpi_clk);
 err_refcount:
dpi->refcount--;
return ret;
@@ -893,6 +903,12 @@ static int mtk_dpi_probe(struct platform_device *pdev)
return ret;
}
 
+   dpi->dpi_clk = devm_clk_get_optional(dev, "dpi");
+   if (IS_ERR(dpi->dpi_clk)) {
+   return dev_err_probe(dev, ret, "Failed to get dpi clock: %pe\n",
+dpi->dpi_clk);
+   }
+
dpi->irq = platform_get_irq(pdev, 0);
if (dpi->irq <= 0)
return -EINVAL;
-- 
2.36.1



Re: mainline build failure due to f1e4c916f97f ("drm/edid: add EDID block count and size helpers")

2022-05-31 Thread Arnd Bergmann
On Tue, May 31, 2022 at 8:26 AM Julia Lawall  wrote:
> > On 30 May 2022, at 15:27, Arnd Bergmann  wrote:
> > On Mon, May 30, 2022 at 4:08 PM Jani Nikula  wrote:
> >>> On Mon, 30 May 2022, Arnd Bergmann  wrote:
> >>> struct my_driver_priv {
> >>>   struct device dev;
> >>>   u8 causes_misalignment;
> >>>   spinlock_t lock;
> >>>   atomic_t counter;
> >>> } __packed; /* this annotation is harmful because it breaks the atomics */
> >>
> >> I wonder if this is something that could be caught with coccinelle. Or
> >> sparse. Are there any cases where this combo is necessary? (I can't
> >> think of any, but it's a low bar. ;)
> >>
...
> >>> or if the annotation does not change the layout like
> >>>
> >>> struct my_dma_descriptor {
> >>> __le64 address;
> >>> __le64 length;
> >>> } __packed; /* does not change layout but makes access slow on some
> >>> architectures */
> >>
> >> Why is this the case, though? I'd imagine the compiler could figure this
> >> out.
> >
> > When you annotate the entire structure as __packed without an
> > extra __aligned() annotation, the compiler has to assume that the
> > structure itself is unaligned as well. On many of the older architectures,
> > this will result in accessing the values one byte at a time. Marking
> > the structure as "__packed __aligned(8)" instead would be harmless.
> >
> > When I have a structure with a few misaligned members, I generally
> > prefer to only annotate the members that are not naturally aligned,
> > but this approach is not very common.
>
> Searching for specific types in a packed structure would be easy.

As an experiment: what kind of results would we get when looking
for packed structures and unions that contain any of these:

- spinlock_t
- atomic_t
- dma_addr_t
- phys_addr_t
- size_t
- any pointer
- any enum
- struct mutex
- struct device

This is just a list of common data types that are used in a lot of
structures but that one should never find in hardware specific
types. If the output from coccinelle is 90% actual bugs, this would
be really helpful. OTOH if there is no output at all, or all
false-positives, we don't need to look for additional types.

> Coccinelle could duplicate the structure without the packed and see if
> any offsets change, using build bug on, but that would be architecture
> specific so maybe not useful.

I would consider this a separate issue. The first one above is for identifying
structures that are marked as packed but should not be packed at
all, regardless of whether that changes the layout.

   Arnd


Re: (EXT) [PATCH 5/6] dt-bindings: drm/bridge: ti-sn65dsi83: Add reset controller documentation

2022-05-31 Thread Marco Felsch
Hi Alexander,

On 22-05-31, Alexander Stein wrote:
> Hi Marco,
> 
> Am Montag, 30. Mai 2022, 17:05:48 CEST schrieb Marco Felsch:
> > The bridge device can now also be enabled/disabled by an external reset
> > controller. So the device now supports either enable/disable by simple
> > GPIO or by an Reset-Controller.
> > 
> > Signed-off-by: Marco Felsch 
> > ---
> >  .../devicetree/bindings/display/bridge/ti,sn65dsi83.yaml| 6 ++
> >  1 file changed, 6 insertions(+)
> > 
> > diff --git
> > a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml
> > b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml index
> > 7306b9874dc3..eff8360c184e 100644
> > --- a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml
> > +++ b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml
> > @@ -35,6 +35,12 @@ properties:
> >vcc-supply:
> >  description: A 1.8V power supply (see regulator/regulator.yaml).
> > 
> > +  resets:
> > +maxItems: 1
> > +description: |
> > +  Reset specifier for bridge_en pin. This is required only if the
> > brdige_en +  pin is connected to a reset controller.
> > +
> >ports:
> >  $ref: /schemas/graph.yaml#/properties/ports
> 
> Maybe it should be added here, that 'resets' is an alternative to 'enable-
> gpios' as both are essentially controlling the same pin from the bridge.

I mention the bridge_en pin two times :) But I could also add that this
is an alternative to the enable-gpios. Maybe it even more clear than.

Regards,
  Marco

> 
> Best regards
> Alexander
> 
> 
> 


Re: (EXT) [PATCH v0 09/10] arm64: dts: imx8mp: add HDMI display pipeline

2022-05-31 Thread Alexander Stein
Hi Lucas,

Am Mittwoch, 6. April 2022, 18:01:22 CEST schrieb Lucas Stach:
> This adds the DT nodes for all the peripherals that make up the
> HDMI display pipeline.
> 
> Signed-off-by: Lucas Stach 
> ---
>  arch/arm64/boot/dts/freescale/imx8mp.dtsi | 80 +++
>  1 file changed, 80 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> b/arch/arm64/boot/dts/freescale/imx8mp.dtsi index
> 6b7b5ba32b48..a41da99e9537 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> @@ -1087,6 +1087,86 @@ irqsteer_hdmi: interrupt-controller@32fc2000 {
>   clock-names = "ipg";
>   power-domains = <&hdmi_blk_ctrl 
IMX8MP_HDMIBLK_PD_IRQSTEER>;
>   };
> +
> + hdmi_pvi: display-bridge@32fc4000 {
> + compatible = "fsl,imx8mp-hdmi-
pvi";
> + reg = <0x32fc4000 0x40>;
> + power-domains = <&hdmi_blk_ctrl 
IMX8MP_HDMIBLK_PD_PVI>;

This should be disabled by default as well. Unless 'hdmi_tx: hdmi@32fd8000' is 
enabled, this results in the warning:
imx-hdmi-pvi: probe of 32fc4000.display-bridge failed with error -22

Best regards
Alexander

> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + 
pvi_from_lcdif3: endpoint {
> + 
remote-endpoint = <&lcdif3_to_pvi>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> + 
pvi_to_hdmi_tx: endpoint {
> + 
remote-endpoint = <&hdmi_tx_from_pvi>;
> + };
> + };
> + };
> + };
> +
> + lcdif3: display-controller@32fc6000 {
> + compatible = "fsl,imx8mp-lcdif";
> + reg = <0x32fc6000 0x238>;
> + interrupts = <8 
IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-parent = 
<&irqsteer_hdmi>;
> + clocks = <&hdmi_tx_phy>,
> +  <&clk 
IMX8MP_CLK_HDMI_APB>,
> +  <&clk 
IMX8MP_CLK_HDMI_ROOT>;
> + clock-names = "pix", "axi", 
"disp_axi";
> + power-domains = <&hdmi_blk_ctrl 
IMX8MP_HDMIBLK_PD_LCDIF>;
> +
> + port {
> + lcdif3_to_pvi: endpoint 
{
> + remote-
endpoint = <&pvi_from_lcdif3>;
> + };
> + };
> + };
> +
> + hdmi_tx: hdmi@32fd8000 {
> + compatible = "fsl,imx8mp-hdmi";
> + reg = <0x32fd8000 0x7eff>;
> + interrupts = <0 
IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-parent = 
<&irqsteer_hdmi>;
> + clocks = <&clk 
IMX8MP_CLK_HDMI_APB>,
> +  <&clk 
IMX8MP_CLK_HDMI_REF_266M>,
> +  <&clk IMX8MP_CLK_32K>,
> +  <&hdmi_tx_phy>;
> + clock-names = "iahb", "isfr", 
"cec", "pix";
> + assigned-clocks = <&clk 
IMX8MP_CLK_HDMI_REF_266M>;
> + assigned-clock-parents = <&clk 
IMX8MP_SYS_PLL1_266M>;
> + power-domains = <&hdmi_blk_ctrl 
IMX8MP_HDMIBLK_PD_HDMI_TX>;
> + reg-io-width = <1>;
> + status = "disabled";
> +
> + port {
> + hdmi_tx_from_pvi: 
endpoint {
> + remote-
endpoint = <&pvi_to_hdmi_tx>;
> + };
> + };
> + };
> +
> + hdmi_tx_phy: phy@32fdff00 {
> + compatible = "fsl,imx8mp-hdmi-
phy";
> + reg = <0x32fdff00 0x100>;
> + clocks = <&clk 
IMX8MP_CLK_HDMI_APB>,
> +  <&clk 
IMX8MP_CLK_HDMI_24M>;
> + clock-names = "apb", "ref";
> + 

Re: [RFC PATCH 00/16] drm/rockchip: Rockchip EBC ("E-Book Controller") display driver

2022-05-31 Thread Maxime Ripard
Hi Daniel,

Thanks for your feedback

On Wed, May 25, 2022 at 07:18:07PM +0200, Daniel Vetter wrote:
> > > VBLANK Events and Asynchronous Commits
> > > ==
> > > When should the VBLANK event complete? When the pixels have been blitted
> > > to the kernel's shadow buffer? When the first frame of the waveform is
> > > sent to the panel? When the last frame is sent to the panel?
> > > 
> > > Currently, the driver is taking the first option, letting
> > > drm_atomic_helper_fake_vblank() send the VBLANK event without waiting on
> > > the refresh thread. This is the only way I was able to get good
> > > performance with existing userspace.
> > 
> > I've been having the same kind of discussions in private lately, so I'm
> > interested by the answer as well :)
> > 
> > It would be worth looking into the SPI/I2C panels for this, since it's
> > basically the same case.
> 
> So it's maybe a bit misnamed and maybe kerneldocs aren't super clear (pls
> help improve them), but there's two modes:
> 
> - drivers which have vblank, which might be somewhat variable (VRR) or
>   become simulated (self-refresh panels), but otherwise is a more-or-less
>   regular clock. For this case the atomic commit event must match the
>   vblank events exactly (frame count and timestamp)

Part of my interrogation there is do we have any kind of expectation
on whether or not, when we commit, the next vblank is going to be the
one matching that commit or we're allowed to defer it by an arbitrary
number of frames (provided that the frame count and timestamps are
correct) ?

> - drivers which don't have vblank at all, mostly these are i2c/spi panels
>   or virtual hw and stuff like that. In this case the event simply happens
>   when the driver is done with refresh/upload, and the frame count should
>   be zero (since it's meaningless).
> 
> Unfortuantely the helper to dtrt has fake_vblank in it's name, maybe
> should be renamed to no_vblank or so (the various flags that control it
> are a bit better named).
> 
> Again the docs should explain it all, but maybe we should clarify them or
> perhaps rename that helper to be more meaningful.
> 
> > > Blitting/Blending in Software
> > > =
> > > There are multiple layers to this topic (pun slightly intended):
> > >  1) Today's userspace does not expect a grayscale framebuffer.
> > > Currently, the driver advertises XRGB and converts to Y4
> > > in software. This seems to match other drivers (e.g. repaper).
> > >
> > >  2) Ignoring what userspace "wants", the closest existing format is
> > > DRM_FORMAT_R8. Geert sent a series[4] adding DRM_FORMAT_R1 through
> > > DRM_FORMAT_R4 (patch 9), which I believe are the "correct" formats
> > > to use.
> > > 
> > >  3) The RK356x SoCs have an "RGA" hardware block that can do the
> > > RGB-to-grayscale conversion, and also RGB-to-dithered-monochrome
> > > which is needed for animation/video. Currently this is exposed with
> > > a V4L2 platform driver. Can this be inserted into the pipeline in a
> > > way that is transparent to userspace? Or must some userspace library
> > > be responsible for setting up the RGA => EBC pipeline?
> > 
> > I'm very interested in this answer as well :)
> > 
> > I think the current consensus is that it's up to userspace to set this
> > up though.
> 
> Yeah I think v4l mem2mem device is the answer for these, and then
> userspace gets to set it all up.

I think the question wasn't really about where that driver should be,
but more about who gets to set it up, and if the kernel could have
some component to expose the formats supported by the converter, but
whenever a commit is being done pipe that to the v4l2 device before
doing a page flip.

We have a similar use-case for the RaspberryPi where the hardware
codec will produce a framebuffer format that isn't standard. That
format is understood by the display pipeline, and it can do
writeback.

However, some people are using a separate display (like a SPI display
supported by tinydrm) and we would still like to be able to output the
decoded frames there.

Is there some way we could plumb things to "route" that buffer through
the writeback engine to perform a format conversion before sending it
over to the SPI display automatically?

Maxime


Re: [PATCH v3 1/3] dt-bindings: vendor-prefixes: Add prefix for EBBG

2022-05-31 Thread Linus Walleij
On Mon, May 30, 2022 at 6:08 PM Joel Selvaraj  wrote:

> Add a prefix for EBBG. They manufacture displays which are used in some
> Xiaomi phones, but I could not find much details about the company.
>
> Signed-off-by: Joel Selvaraj 
> Acked-by: Krzysztof Kozlowski 

Acked-by: Linus Walleij 

Yours,
Linus Walleij


Re: [PATCH v3 3/3] drm/panel: introduce ebbg,ft8719 panel

2022-05-31 Thread Linus Walleij
Hi Joel,

On Mon, May 30, 2022 at 6:08 PM Joel Selvaraj  wrote:

> +#define dsi_dcs_write_seq(dsi, cmd, seq...) do { 
>   \

Please name it mipi_dsi_dcs_write_seq() and...

> +   static const u8 d[] = { cmd, seq };   
>   \
> +   struct device *dev = &dsi->dev; \
> +   int ret;\
> +   ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
> +   if (ret < 0) {  \
> +   dev_err_ratelimited(dev, "sending command %#02x 
> failed: %d\n", cmd, ret); \
> +   return ret;   
>   \
> +   }   \
> +   } while (0)

My suggestion was to add this macro to include/drm/drm_mipi_dsi.h, just patch it
in there under the other mipi_dsi_dcs_* functions.

I think a few other drivers could make good use of this macro.

Yours,
Linus Walleij


Re: [PATCH 14/14] drm/vc4: Warn if some v3d code is run on BCM2711

2022-05-31 Thread Maxime Ripard
Hi Melissa,

On Mon, May 09, 2022 at 03:52:04PM -0100, Melissa Wen wrote:
> > @@ -915,10 +954,14 @@ int vc4_set_tiling_ioctl(struct drm_device *dev, void 
> > *data,
> >  int vc4_get_tiling_ioctl(struct drm_device *dev, void *data,
> >  struct drm_file *file_priv)
> >  {
> > +   struct vc4_dev *vc4 = to_vc4_dev(dev);
> > struct drm_vc4_get_tiling *args = data;
> > struct drm_gem_object *gem_obj;
> > struct vc4_bo *bo;
> >  
> > +   if (WARN_ON_ONCE(vc4->is_vc5))
> > +   return -ENODEV;
> > +
> 
> Just to confirm: as none of these ioctls were wired up in
> vc5_drm_driver, is there any situation where this path can be taken
> wrongly?

For this particular function, no, it wasn't reachable before since the
ioctl were only exposed for devices with the render capability, and we
were not using it.

Other functions in that patch however are called prior to this series,
especially in the BO/GEM related path.

Maxime


[PATCH] drm/edid: ignore the CEA modes not defined in CEA-861-D

2022-05-31 Thread William Tseng
This is a workaround for HDMI 1.4 sink which has a CEA mode with higher vic
than what is defined in CEA-861-D.

As an example, a HDMI 1.4 sink has the video format 2560x1080p to be
displayed and the video format is indicated by both SVD (with vic 90 and
pictuure aspect ratio 64:27) and DTD.  When connecting to such sink,
source can't output the video format in SVD because an error is returned by
drm_hdmi_avi_infoframe_from_display_mode(), which can't fill the infoframe
with pictuure aspect ratio 64:27 and the vic, which is originally 90 and is
changed to 0 by drm_mode_cea_vic().

To work around it, this patch ignores such CEA modes in do_cea_modes() so
the modes won't be processed in drm_hdmi_avi_infoframe_from_display_mode().
And only the video format in DTD can be dispalyed.

Cc: Ville Syrjälä 
Cc: Wayne Lin 
Cc: Lee Shawn C 
Signed-off-by: William Tseng 
---
 drivers/gpu/drm/drm_edid.c | 39 +-
 1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index bc43e1b32092..a93f68878bfd 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3982,6 +3982,19 @@ drm_display_mode_from_cea_vic(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_display_mode_from_cea_vic);
 
+static bool is_hdmi2_sink(const struct drm_connector *connector)
+{
+   /*
+* FIXME: sil-sii8620 doesn't have a connector around when
+* we need one, so we have to be prepared for a NULL connector.
+*/
+   if (!connector)
+   return true;
+
+   return connector->display_info.hdmi.scdc.supported ||
+   connector->display_info.color_formats & 
DRM_COLOR_FORMAT_YCBCR420;
+}
+
 static int
 do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
 {
@@ -3993,6 +4006,19 @@ do_cea_modes(struct drm_connector *connector, const u8 
*db, u8 len)
 
mode = drm_display_mode_from_vic_index(connector, db, len, i);
if (mode) {
+   u8 vic = svd_to_vic(db[i]);
+
+   if (!drm_valid_cea_vic(vic))
+   continue;
+
+   /*
+* HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
+* HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So 
we
+* have to make sure we dont break HDMI 1.4 sinks.
+*/
+   if (!is_hdmi2_sink(connector) && vic > 64)
+   continue;
+
/*
 * YCBCR420 capability block contains a bitmap which
 * gives the index of CEA modes from CEA VDB, which
@@ -5846,19 +5872,6 @@ void drm_set_preferred_mode(struct drm_connector 
*connector,
 }
 EXPORT_SYMBOL(drm_set_preferred_mode);
 
-static bool is_hdmi2_sink(const struct drm_connector *connector)
-{
-   /*
-* FIXME: sil-sii8620 doesn't have a connector around when
-* we need one, so we have to be prepared for a NULL connector.
-*/
-   if (!connector)
-   return true;
-
-   return connector->display_info.hdmi.scdc.supported ||
-   connector->display_info.color_formats & 
DRM_COLOR_FORMAT_YCBCR420;
-}
-
 static u8 drm_mode_hdmi_vic(const struct drm_connector *connector,
const struct drm_display_mode *mode)
 {
-- 
2.17.1



Re: [RFC] drm/kms: control display brightness through drm_connector properties

2022-05-31 Thread Hans de Goede
Hi,

On 5/18/22 16:23, Jani Nikula wrote:
> On Wed, 18 May 2022, Hans de Goede  wrote:
>> So how about: display_brightness or panel_brightness ?
> 
> This is a prime opportunity to look at all the existing properties, and
> come up with a new combination of capitalization, spacing, hyphens,
> underscores, etc. to accompany the total lack of unification we
> currently have. DisPLay_brIgh7ne55. :p
> 
> I think "display_brightness" is probably fine.

Interesting remark about the use of space/_/- I checked drm_connector.c
and most properties use all lower case with spaces so to try and be consistent,
I'll replace the _ with a space.

I guess it is time for me to create a v2 of this proposal.

Regards,

Hans



Re: [PATCH] drm/edid: ignore the CEA modes not defined in CEA-861-D

2022-05-31 Thread Jani Nikula
On Tue, 31 May 2022, William Tseng  wrote:
> This is a workaround for HDMI 1.4 sink which has a CEA mode with higher vic
> than what is defined in CEA-861-D.
>
> As an example, a HDMI 1.4 sink has the video format 2560x1080p to be
> displayed and the video format is indicated by both SVD (with vic 90 and
> pictuure aspect ratio 64:27) and DTD.  When connecting to such sink,
> source can't output the video format in SVD because an error is returned by
> drm_hdmi_avi_infoframe_from_display_mode(), which can't fill the infoframe
> with pictuure aspect ratio 64:27 and the vic, which is originally 90 and is
> changed to 0 by drm_mode_cea_vic().
>
> To work around it, this patch ignores such CEA modes in do_cea_modes() so
> the modes won't be processed in drm_hdmi_avi_infoframe_from_display_mode().
> And only the video format in DTD can be dispalyed.
>
> Cc: Ville Syrjälä 
> Cc: Wayne Lin 
> Cc: Lee Shawn C 
> Signed-off-by: William Tseng 
> ---
>  drivers/gpu/drm/drm_edid.c | 39 +-
>  1 file changed, 26 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index bc43e1b32092..a93f68878bfd 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -3982,6 +3982,19 @@ drm_display_mode_from_cea_vic(struct drm_device *dev,
>  }
>  EXPORT_SYMBOL(drm_display_mode_from_cea_vic);
>  
> +static bool is_hdmi2_sink(const struct drm_connector *connector)
> +{
> + /*
> +  * FIXME: sil-sii8620 doesn't have a connector around when
> +  * we need one, so we have to be prepared for a NULL connector.
> +  */
> + if (!connector)
> + return true;
> +
> + return connector->display_info.hdmi.scdc.supported ||
> + connector->display_info.color_formats & 
> DRM_COLOR_FORMAT_YCBCR420;
> +}
> +
>  static int
>  do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
>  {
> @@ -3993,6 +4006,19 @@ do_cea_modes(struct drm_connector *connector, const u8 
> *db, u8 len)
>  
>   mode = drm_display_mode_from_vic_index(connector, db, len, i);
>   if (mode) {
> + u8 vic = svd_to_vic(db[i]);
> +
> + if (!drm_valid_cea_vic(vic))
> + continue;

drm_display_mode_from_vic_index() returns NULL in this case.

> +
> + /*
> +  * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
> +  * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So 
> we
> +  * have to make sure we dont break HDMI 1.4 sinks.
> +  */
> + if (!is_hdmi2_sink(connector) && vic > 64)
> + continue;

I'll need to double check if this is the right thing to do... but I
guess the question becomes if this shouldn't be within
drm_display_mode_from_vic_index().

Duplicating the condition from drm_mode_cea_vic() is probably not a good
idea.

The continues in both above branches leak the mode.


BR,
Jani.


> +
>   /*
>* YCBCR420 capability block contains a bitmap which
>* gives the index of CEA modes from CEA VDB, which
> @@ -5846,19 +5872,6 @@ void drm_set_preferred_mode(struct drm_connector 
> *connector,
>  }
>  EXPORT_SYMBOL(drm_set_preferred_mode);
>  
> -static bool is_hdmi2_sink(const struct drm_connector *connector)
> -{
> - /*
> -  * FIXME: sil-sii8620 doesn't have a connector around when
> -  * we need one, so we have to be prepared for a NULL connector.
> -  */
> - if (!connector)
> - return true;
> -
> - return connector->display_info.hdmi.scdc.supported ||
> - connector->display_info.color_formats & 
> DRM_COLOR_FORMAT_YCBCR420;
> -}
> -
>  static u8 drm_mode_hdmi_vic(const struct drm_connector *connector,
>   const struct drm_display_mode *mode)
>  {

-- 
Jani Nikula, Intel Open Source Graphics Center


Re: [PATCH v10 0/4] Separate panel orientation property creating and value setting

2022-05-31 Thread Hans de Goede
Hi,

On 5/30/22 13:34, Hsin-Yi Wang wrote:
> On Mon, May 30, 2022 at 4:53 PM Hans de Goede  wrote:
>>
>> Hi,
>>
>> On 5/30/22 10:19, Hsin-Yi Wang wrote:
>>> Some drivers, eg. mtk_drm and msm_drm, rely on the panel to set the
>>> orientation. Panel calls drm_connector_set_panel_orientation() to create
>>> orientation property and sets the value. However, connector properties
>>> can't be created after drm_dev_register() is called. The goal is to
>>> separate the orientation property creation, so drm drivers can create it
>>> earlier before drm_dev_register().
>>
>> Sorry for jumping in pretty late in the discussion (based on the v10
>> I seem to have missed this before).
>>
>> This sounds to me like the real issue here is that drm_dev_register()
>> is getting called too early?
>>
> Right.
> 
>> To me it seems sensible to delay calling drm_dev_register() and
>> thus allowing userspace to start detecting available displays +
>> features until after the panel has been probed.
>>
> 
> Most panels set this value very late, in .get_modes callback (since it
> is when the connector is known), though the value was known during
> panel probe.

Hmm I would expect the main drm/kms driver to register the drm_connector
object after probing the panel, right ?

So maybe this is a problem with the panel API? How about adding 
separate callback to the panel API to get the orientation, which the
main drm/kms driver can then call before registering the connector ?

And then have the main drm/kms driver call
drm_connector_set_panel_orientation() with the returned orientation
on the connecter before registering it.

The new get_orientation callback for the panel should of course
be optional (IOW amy be NULL), so we probably want a small
helper for drivers using panel (sub)drivers to take care of
the process of getting the panel orientation from the panel
(if supported) and then setting it on the connector.


> I think we can also let drm check if they have remote panel nodes: If
> there is a panel and the panel sets the orientation, let the drm read
> this value and set the property. Does this workflow sound reasonable?
> 
> The corresponding patch to implement this:
> https://patchwork.kernel.org/project/linux-mediatek/patch/20220530113033.124072-1-hsi...@chromium.org/

That is a suprisingly small patch (which is good). I guess that
my suggestion to add a new panel driver callback to get
the orientation would be a bit bigget then this. Still I think
that that would be a bit cleaner, as it would also solve this
for cases where the orientation comes from the panel itself
(through say some EDID extenstion) rather then from devicetree.

Still I think either way should be acceptable upstream.

Opinions from other drm devs on the above are very much welcome!

Your small patch nicely avoids the probe ordering problem,
so it is much better then this patch series.

Regards,

Hans



> 
> Thanks
> 
>> I see a devicetree patch in this series, so I guess that the panel
>> is described in devicetree. Especially in the case of devicetree
>> I would expect the kernel to have enough info to do the right
>> thing and make sure the panel is probed before calling
>> drm_dev_register() ?
>>
>> Regards,
>>
>> Hans
>>
>>
>>
>>
>>>
>>> After this series, drm_connector_set_panel_orientation() works like
>>> before. It won't affect existing callers of
>>> drm_connector_set_panel_orientation(). The only difference is that
>>> some drm drivers can call drm_connector_init_panel_orientation_property()
>>> earlier.
>>>
>>> Hsin-Yi Wang (4):
>>>   gpu: drm: separate panel orientation property creating and value
>>> setting
>>>   drm/mediatek: init panel orientation property
>>>   drm/msm: init panel orientation property
>>>   arm64: dts: mt8183: Add panel rotation
>>>
>>>  .../arm64/boot/dts/mediatek/mt8183-kukui.dtsi |  1 +
>>>  drivers/gpu/drm/drm_connector.c   | 58 ++-
>>>  drivers/gpu/drm/mediatek/mtk_dsi.c|  7 +++
>>>  drivers/gpu/drm/msm/dsi/dsi_manager.c |  4 ++
>>>  include/drm/drm_connector.h   |  2 +
>>>  5 files changed, 59 insertions(+), 13 deletions(-)
>>>
>>
> 



Re: [PATCH] drm/edid: ignore the CEA modes not defined in CEA-861-D

2022-05-31 Thread Jani Nikula
On Tue, 31 May 2022, Jani Nikula  wrote:
> On Tue, 31 May 2022, William Tseng  wrote:
>> This is a workaround for HDMI 1.4 sink which has a CEA mode with higher vic
>> than what is defined in CEA-861-D.
>>
>> As an example, a HDMI 1.4 sink has the video format 2560x1080p to be
>> displayed and the video format is indicated by both SVD (with vic 90 and
>> pictuure aspect ratio 64:27) and DTD.  When connecting to such sink,
>> source can't output the video format in SVD because an error is returned by
>> drm_hdmi_avi_infoframe_from_display_mode(), which can't fill the infoframe
>> with pictuure aspect ratio 64:27 and the vic, which is originally 90 and is
>> changed to 0 by drm_mode_cea_vic().
>>
>> To work around it, this patch ignores such CEA modes in do_cea_modes() so
>> the modes won't be processed in drm_hdmi_avi_infoframe_from_display_mode().
>> And only the video format in DTD can be dispalyed.

I think we should also have a bug filed on this, with the offending EDID
attached for posterity.

BR,
Jani.


>>
>> Cc: Ville Syrjälä 
>> Cc: Wayne Lin 
>> Cc: Lee Shawn C 
>> Signed-off-by: William Tseng 
>> ---
>>  drivers/gpu/drm/drm_edid.c | 39 +-
>>  1 file changed, 26 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index bc43e1b32092..a93f68878bfd 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -3982,6 +3982,19 @@ drm_display_mode_from_cea_vic(struct drm_device *dev,
>>  }
>>  EXPORT_SYMBOL(drm_display_mode_from_cea_vic);
>>  
>> +static bool is_hdmi2_sink(const struct drm_connector *connector)
>> +{
>> +/*
>> + * FIXME: sil-sii8620 doesn't have a connector around when
>> + * we need one, so we have to be prepared for a NULL connector.
>> + */
>> +if (!connector)
>> +return true;
>> +
>> +return connector->display_info.hdmi.scdc.supported ||
>> +connector->display_info.color_formats & 
>> DRM_COLOR_FORMAT_YCBCR420;
>> +}
>> +
>>  static int
>>  do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
>>  {
>> @@ -3993,6 +4006,19 @@ do_cea_modes(struct drm_connector *connector, const 
>> u8 *db, u8 len)
>>  
>>  mode = drm_display_mode_from_vic_index(connector, db, len, i);
>>  if (mode) {
>> +u8 vic = svd_to_vic(db[i]);
>> +
>> +if (!drm_valid_cea_vic(vic))
>> +continue;
>
> drm_display_mode_from_vic_index() returns NULL in this case.
>
>> +
>> +/*
>> + * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
>> + * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So 
>> we
>> + * have to make sure we dont break HDMI 1.4 sinks.
>> + */
>> +if (!is_hdmi2_sink(connector) && vic > 64)
>> +continue;
>
> I'll need to double check if this is the right thing to do... but I
> guess the question becomes if this shouldn't be within
> drm_display_mode_from_vic_index().
>
> Duplicating the condition from drm_mode_cea_vic() is probably not a good
> idea.
>
> The continues in both above branches leak the mode.
>
>
> BR,
> Jani.
>
>
>> +
>>  /*
>>   * YCBCR420 capability block contains a bitmap which
>>   * gives the index of CEA modes from CEA VDB, which
>> @@ -5846,19 +5872,6 @@ void drm_set_preferred_mode(struct drm_connector 
>> *connector,
>>  }
>>  EXPORT_SYMBOL(drm_set_preferred_mode);
>>  
>> -static bool is_hdmi2_sink(const struct drm_connector *connector)
>> -{
>> -/*
>> - * FIXME: sil-sii8620 doesn't have a connector around when
>> - * we need one, so we have to be prepared for a NULL connector.
>> - */
>> -if (!connector)
>> -return true;
>> -
>> -return connector->display_info.hdmi.scdc.supported ||
>> -connector->display_info.color_formats & 
>> DRM_COLOR_FORMAT_YCBCR420;
>> -}
>> -
>>  static u8 drm_mode_hdmi_vic(const struct drm_connector *connector,
>>  const struct drm_display_mode *mode)
>>  {

-- 
Jani Nikula, Intel Open Source Graphics Center


[PATCH v2 1/5] drm/ast: Support multiple outputs

2022-05-31 Thread Thomas Zimmermann
Systems with AST graphics can have multiple output; typically VGA
plus some other port. Record detected output chips in a bitmask and
initialize each output on its own.

Assume a VGA output by default and use SIL164 and DP501 if available.
For ASTDP assume that it can run in parallel with VGA.

Tested on AST2100.

v2:
* make VGA/SIL164/DP501 mutually exclusive

Signed-off-by: Thomas Zimmermann 
Fixes: a59b026419f3 ("drm/ast: Initialize encoder and connector for VGA in 
helper function")
Cc: Thomas Zimmermann 
Cc: Javier Martinez Canillas 
Cc: Dave Airlie 
Cc: dri-devel@lists.freedesktop.org
---
 drivers/gpu/drm/ast/ast_dp.c|  5 ++---
 drivers/gpu/drm/ast/ast_dp501.c |  2 +-
 drivers/gpu/drm/ast/ast_drv.h   |  4 ++--
 drivers/gpu/drm/ast/ast_main.c  | 21 --
 drivers/gpu/drm/ast/ast_mode.c  | 38 ++---
 drivers/gpu/drm/ast/ast_post.c  |  2 +-
 6 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
index 4551bc8a3ecf..f573d582407e 100644
--- a/drivers/gpu/drm/ast/ast_dp.c
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -160,13 +160,12 @@ void ast_dp_launch(struct drm_device *dev, u8 bPower)
}
 
if (bDPExecute)
-   ast->tx_chip_type = AST_TX_ASTDP;
+   ast->tx_chip_types |= BIT(AST_TX_ASTDP);
 
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
(u8) 
~ASTDP_HOST_EDID_READ_DONE_MASK,

ASTDP_HOST_EDID_READ_DONE);
-   } else
-   ast->tx_chip_type = AST_TX_NONE;
+   }
 }
 
 
diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c
index 204c926a18ea..4f75a9efb610 100644
--- a/drivers/gpu/drm/ast/ast_dp501.c
+++ b/drivers/gpu/drm/ast/ast_dp501.c
@@ -450,7 +450,7 @@ void ast_init_3rdtx(struct drm_device *dev)
ast_init_dvo(dev);
break;
default:
-   if (ast->tx_chip_type == AST_TX_SIL164)
+   if (ast->tx_chip_types & BIT(AST_TX_SIL164))
ast_init_dvo(dev);
else
ast_init_analog(dev);
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index afebe35f205e..3055b0be7b67 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -173,7 +173,7 @@ struct ast_private {
struct drm_plane primary_plane;
struct ast_cursor_plane cursor_plane;
struct drm_crtc crtc;
-   union {
+   struct {
struct {
struct drm_encoder encoder;
struct ast_vga_connector vga_connector;
@@ -199,7 +199,7 @@ struct ast_private {
ast_use_defaults
} config_mode;
 
-   enum ast_tx_chip tx_chip_type;
+   unsigned long tx_chip_types;/* bitfield of enum 
ast_chip_type */
u8 *dp501_fw_addr;
const struct firmware *dp501_fw;/* dp501 fw */
 };
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index d770d5a23c1a..50b8d51382c7 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -216,7 +216,7 @@ static int ast_detect_chip(struct drm_device *dev, bool 
*need_post)
}
 
/* Check 3rd Tx option (digital output afaik) */
-   ast->tx_chip_type = AST_TX_NONE;
+   ast->tx_chip_types |= BIT(AST_TX_NONE);
 
/*
 * VGACRA3 Enhanced Color Mode Register, check if DVO is already
@@ -229,7 +229,7 @@ static int ast_detect_chip(struct drm_device *dev, bool 
*need_post)
if (!*need_post) {
jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 
0xff);
if (jreg & 0x80)
-   ast->tx_chip_type = AST_TX_SIL164;
+   ast->tx_chip_types = BIT(AST_TX_SIL164);
}
 
if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == 
AST2500)) {
@@ -241,7 +241,7 @@ static int ast_detect_chip(struct drm_device *dev, bool 
*need_post)
jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 
0xff);
switch (jreg) {
case 0x04:
-   ast->tx_chip_type = AST_TX_SIL164;
+   ast->tx_chip_types = BIT(AST_TX_SIL164);
break;
case 0x08:
ast->dp501_fw_addr = drmm_kzalloc(dev, 32*1024, 
GFP_KERNEL);
@@ -254,22 +254,19 @@ static int ast_detect_chip(struct drm_device *dev, bool 
*need_post)
}
fallthrough;
case 0x0c:
-   ast->tx_chip_type = AST_TX_DP501;
+   ast->tx_chip_types = BIT(AST_TX_DP501);
}
}

[PATCH v2 0/5] drm/ast: Connector cleanups and polling

2022-05-31 Thread Thomas Zimmermann
Various cleanups to ast's conenctor code. Simplifies the code, adds
support for using VGA and ASTDP connectors at the same time, and
initializes polling of the connector status.

Patch 1 was first posted at [1], so this patchset starts at version
2. The implementation of detect_ctx in patch 3 has been added to DRM
helpers as it will be useful for other drivers, such as mgag200 and
udl.

Thomas Zimmermann (5):
  drm/ast: Support multiple outputs
  drm/ast: Fix updating the connector's EDID property
  drm/ast: Support output polling
  drm/ast: Fail probing if DCC channel could not be initialized
  drm/ast: Remove struct ast_{vga,sil164}_connector

 drivers/gpu/drm/ast/ast_dp.c   |   5 +-
 drivers/gpu/drm/ast/ast_dp501.c|   2 +-
 drivers/gpu/drm/ast/ast_drv.h  |  30 +-
 drivers/gpu/drm/ast/ast_i2c.c  |   7 +-
 drivers/gpu/drm/ast/ast_main.c |  21 ++--
 drivers/gpu/drm/ast/ast_mode.c | 165 ++---
 drivers/gpu/drm/ast/ast_post.c |   2 +-
 drivers/gpu/drm/drm_probe_helper.c |  35 ++
 include/drm/drm_probe_helper.h |   3 +
 9 files changed, 116 insertions(+), 154 deletions(-)


base-commit: 2c8cc5cd20e28afe6b63acb28890e5f57d9bf055
-- 
2.36.1



[PATCH v2 2/5] drm/ast: Fix updating the connector's EDID property

2022-05-31 Thread Thomas Zimmermann
Read the display modes from the connectors DDC helper, which also
updates the connector's EDID property. The code for the connector's
.get_modes helper is now shared between VGA and SIL164.

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/ast/ast_mode.c | 57 ++
 1 file changed, 2 insertions(+), 55 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index e19dd2f9b3ce..4ff8ec1c8931 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -1302,37 +1302,19 @@ static int ast_crtc_init(struct drm_device *dev)
 
 static int ast_vga_connector_helper_get_modes(struct drm_connector *connector)
 {
-   struct ast_vga_connector *ast_vga_connector = 
to_ast_vga_connector(connector);
struct drm_device *dev = connector->dev;
struct ast_private *ast = to_ast_private(dev);
-   struct edid *edid;
int count;
 
-   if (!ast_vga_connector->i2c)
-   goto err_drm_connector_update_edid_property;
-
/*
 * Protect access to I/O registers from concurrent modesetting
 * by acquiring the I/O-register lock.
 */
mutex_lock(&ast->ioregs_lock);
-
-   edid = drm_get_edid(connector, &ast_vga_connector->i2c->adapter);
-   if (!edid)
-   goto err_mutex_unlock;
-
+   count = drm_connector_helper_get_modes_from_ddc(connector);
mutex_unlock(&ast->ioregs_lock);
 
-   count = drm_add_edid_modes(connector, edid);
-   kfree(edid);
-
return count;
-
-err_mutex_unlock:
-   mutex_unlock(&ast->ioregs_lock);
-err_drm_connector_update_edid_property:
-   drm_connector_update_edid_property(connector, NULL);
-   return 0;
 }
 
 static const struct drm_connector_helper_funcs ast_vga_connector_helper_funcs 
= {
@@ -1406,43 +1388,8 @@ static int ast_vga_output_init(struct ast_private *ast)
  * SIL164 Connector
  */
 
-static int ast_sil164_connector_helper_get_modes(struct drm_connector 
*connector)
-{
-   struct ast_sil164_connector *ast_sil164_connector = 
to_ast_sil164_connector(connector);
-   struct drm_device *dev = connector->dev;
-   struct ast_private *ast = to_ast_private(dev);
-   struct edid *edid;
-   int count;
-
-   if (!ast_sil164_connector->i2c)
-   goto err_drm_connector_update_edid_property;
-
-   /*
-* Protect access to I/O registers from concurrent modesetting
-* by acquiring the I/O-register lock.
-*/
-   mutex_lock(&ast->ioregs_lock);
-
-   edid = drm_get_edid(connector, &ast_sil164_connector->i2c->adapter);
-   if (!edid)
-   goto err_mutex_unlock;
-
-   mutex_unlock(&ast->ioregs_lock);
-
-   count = drm_add_edid_modes(connector, edid);
-   kfree(edid);
-
-   return count;
-
-err_mutex_unlock:
-   mutex_unlock(&ast->ioregs_lock);
-err_drm_connector_update_edid_property:
-   drm_connector_update_edid_property(connector, NULL);
-   return 0;
-}
-
 static const struct drm_connector_helper_funcs 
ast_sil164_connector_helper_funcs = {
-   .get_modes = ast_sil164_connector_helper_get_modes,
+   .get_modes = ast_vga_connector_helper_get_modes, // same as VGA 
connector
 };
 
 static const struct drm_connector_funcs ast_sil164_connector_funcs = {
-- 
2.36.1



[PATCH v2 5/5] drm/ast: Remove struct ast_{vga,sil164}_connector

2022-05-31 Thread Thomas Zimmermann
Both, struct ast_vga_connector and struct ast_sil164_connector, are
now wrappers around struct drm_connector. Remove them.

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/ast/ast_drv.h  | 24 ++--
 drivers/gpu/drm/ast/ast_mode.c | 18 ++
 2 files changed, 8 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 2a55fc7303b9..d456f6bc4b2c 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -130,26 +130,6 @@ struct ast_i2c_chan {
struct i2c_algo_bit_data bit;
 };
 
-struct ast_vga_connector {
-   struct drm_connector base;
-};
-
-static inline struct ast_vga_connector *
-to_ast_vga_connector(struct drm_connector *connector)
-{
-   return container_of(connector, struct ast_vga_connector, base);
-}
-
-struct ast_sil164_connector {
-   struct drm_connector base;
-};
-
-static inline struct ast_sil164_connector *
-to_ast_sil164_connector(struct drm_connector *connector)
-{
-   return container_of(connector, struct ast_sil164_connector, base);
-}
-
 /*
  * Device
  */
@@ -174,11 +154,11 @@ struct ast_private {
struct {
struct {
struct drm_encoder encoder;
-   struct ast_vga_connector vga_connector;
+   struct drm_connector connector;
} vga;
struct {
struct drm_encoder encoder;
-   struct ast_sil164_connector sil164_connector;
+   struct drm_connector connector;
} sil164;
struct {
struct drm_encoder encoder;
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 5f273b5dd769..326f29dae844 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -1330,10 +1330,8 @@ static const struct drm_connector_funcs 
ast_vga_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int ast_vga_connector_init(struct drm_device *dev,
- struct ast_vga_connector *ast_vga_connector)
+static int ast_vga_connector_init(struct drm_device *dev, struct drm_connector 
*connector)
 {
-   struct drm_connector *connector = &ast_vga_connector->base;
struct ast_i2c_chan *i2c;
int ret;
 
@@ -1364,8 +1362,7 @@ static int ast_vga_output_init(struct ast_private *ast)
struct drm_device *dev = &ast->base;
struct drm_crtc *crtc = &ast->crtc;
struct drm_encoder *encoder = &ast->output.vga.encoder;
-   struct ast_vga_connector *ast_vga_connector = 
&ast->output.vga.vga_connector;
-   struct drm_connector *connector = &ast_vga_connector->base;
+   struct drm_connector *connector = &ast->output.vga.connector;
int ret;
 
ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DAC);
@@ -1373,7 +1370,7 @@ static int ast_vga_output_init(struct ast_private *ast)
return ret;
encoder->possible_crtcs = drm_crtc_mask(crtc);
 
-   ret = ast_vga_connector_init(dev, ast_vga_connector);
+   ret = ast_vga_connector_init(dev, connector);
if (ret)
return ret;
 
@@ -1401,10 +1398,8 @@ static const struct drm_connector_funcs 
ast_sil164_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int ast_sil164_connector_init(struct drm_device *dev,
-struct ast_sil164_connector 
*ast_sil164_connector)
+static int ast_sil164_connector_init(struct drm_device *dev, struct 
drm_connector *connector)
 {
-   struct drm_connector *connector = &ast_sil164_connector->base;
struct ast_i2c_chan *i2c;
int ret;
 
@@ -1435,8 +1430,7 @@ static int ast_sil164_output_init(struct ast_private *ast)
struct drm_device *dev = &ast->base;
struct drm_crtc *crtc = &ast->crtc;
struct drm_encoder *encoder = &ast->output.sil164.encoder;
-   struct ast_sil164_connector *ast_sil164_connector = 
&ast->output.sil164.sil164_connector;
-   struct drm_connector *connector = &ast_sil164_connector->base;
+   struct drm_connector *connector = &ast->output.sil164.connector;
int ret;
 
ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
@@ -1444,7 +1438,7 @@ static int ast_sil164_output_init(struct ast_private *ast)
return ret;
encoder->possible_crtcs = drm_crtc_mask(crtc);
 
-   ret = ast_sil164_connector_init(dev, ast_sil164_connector);
+   ret = ast_sil164_connector_init(dev, connector);
if (ret)
return ret;
 
-- 
2.36.1



[PATCH v2 3/5] drm/ast: Support output polling

2022-05-31 Thread Thomas Zimmermann
Enable output polling for all connectors. VGA always uses EDID for this. As
there's currently no interrupt handling for the ast devices, we have to use
that trick for the various DP and DVI ports as well.

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/ast/ast_mode.c | 14 
 drivers/gpu/drm/drm_probe_helper.c | 35 ++
 include/drm/drm_probe_helper.h |  3 +++
 3 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 4ff8ec1c8931..bbc566c4c768 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -1319,6 +1319,7 @@ static int ast_vga_connector_helper_get_modes(struct 
drm_connector *connector)
 
 static const struct drm_connector_helper_funcs ast_vga_connector_helper_funcs 
= {
.get_modes = ast_vga_connector_helper_get_modes,
+   .detect_ctx = drm_connector_helper_detect_ctx_from_edid,
 };
 
 static const struct drm_connector_funcs ast_vga_connector_funcs = {
@@ -1354,7 +1355,7 @@ static int ast_vga_connector_init(struct drm_device *dev,
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
 
-   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+   connector->polled = DRM_CONNECTOR_POLL_CONNECT | 
DRM_CONNECTOR_POLL_DISCONNECT;
 
return 0;
 }
@@ -1390,6 +1391,7 @@ static int ast_vga_output_init(struct ast_private *ast)
 
 static const struct drm_connector_helper_funcs 
ast_sil164_connector_helper_funcs = {
.get_modes = ast_vga_connector_helper_get_modes, // same as VGA 
connector
+   .detect_ctx = drm_connector_helper_detect_ctx_from_edid,
 };
 
 static const struct drm_connector_funcs ast_sil164_connector_funcs = {
@@ -1425,7 +1427,7 @@ static int ast_sil164_connector_init(struct drm_device 
*dev,
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
 
-   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+   connector->polled = DRM_CONNECTOR_POLL_CONNECT | 
DRM_CONNECTOR_POLL_DISCONNECT;
 
return 0;
 }
@@ -1488,6 +1490,7 @@ static int ast_dp501_connector_helper_get_modes(struct 
drm_connector *connector)
 
 static const struct drm_connector_helper_funcs 
ast_dp501_connector_helper_funcs = {
.get_modes = ast_dp501_connector_helper_get_modes,
+   .detect_ctx = drm_connector_helper_detect_ctx_from_edid,
 };
 
 static const struct drm_connector_funcs ast_dp501_connector_funcs = {
@@ -1512,7 +1515,7 @@ static int ast_dp501_connector_init(struct drm_device 
*dev, struct drm_connector
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
 
-   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+   connector->polled = DRM_CONNECTOR_POLL_CONNECT | 
DRM_CONNECTOR_POLL_DISCONNECT;
 
return 0;
 }
@@ -1575,6 +1578,7 @@ static int ast_astdp_connector_helper_get_modes(struct 
drm_connector *connector)
 
 static const struct drm_connector_helper_funcs 
ast_astdp_connector_helper_funcs = {
.get_modes = ast_astdp_connector_helper_get_modes,
+   .detect_ctx = drm_connector_helper_detect_ctx_from_edid,
 };
 
 static const struct drm_connector_funcs ast_astdp_connector_funcs = {
@@ -1599,7 +1603,7 @@ static int ast_astdp_connector_init(struct drm_device 
*dev, struct drm_connector
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
 
-   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+   connector->polled = DRM_CONNECTOR_POLL_CONNECT | 
DRM_CONNECTOR_POLL_DISCONNECT;
 
return 0;
 }
@@ -1709,5 +1713,7 @@ int ast_mode_config_init(struct ast_private *ast)
 
drm_mode_config_reset(dev);
 
+   drm_kms_helper_poll_init(dev);
+
return 0;
 }
diff --git a/drivers/gpu/drm/drm_probe_helper.c 
b/drivers/gpu/drm/drm_probe_helper.c
index 425f56280d51..4440a7b6b240 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -1031,3 +1031,38 @@ int drm_connector_helper_get_modes_from_ddc(struct 
drm_connector *connector)
return count;
 }
 EXPORT_SYMBOL(drm_connector_helper_get_modes_from_ddc);
+
+/**
+ * drm_connector_helper_detect_ctx_from_edid -
+ * Updates the connector's status by reading EDID data
+ * @connector: The connector.
+ * @ctx: The lock-acquisition context.
+ * @force: True if the operation was requested by userspace, false otherwise.
+ *
+ * Returns:
+ * The connector's status as enum drm_connector_status.
+ *
+ * Updates the connector's EDID property by reading the display modes
+ * and returns the connector's status. If the EDID property is set, the
+ * connector is assumed to be connected; and disconnected otherwise.
+ * If the get_modes helper is missing, the default status is 'unknown'.
+ *
+ * See struct drm_connector_helper_funcs.detect_ctx.
+ */
+int drm_connector_helper_detect_ctx_from_edid(struct drm_connector *connector,
+ s

[PATCH v2 4/5] drm/ast: Fail probing if DCC channel could not be initialized

2022-05-31 Thread Thomas Zimmermann
Expect the hardware to provide a DDC channel. Fail probing if its
initialization fails.

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/ast/ast_drv.h  |  2 --
 drivers/gpu/drm/ast/ast_i2c.c  |  7 ---
 drivers/gpu/drm/ast/ast_mode.c | 38 --
 3 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 3055b0be7b67..2a55fc7303b9 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -132,7 +132,6 @@ struct ast_i2c_chan {
 
 struct ast_vga_connector {
struct drm_connector base;
-   struct ast_i2c_chan *i2c;
 };
 
 static inline struct ast_vga_connector *
@@ -143,7 +142,6 @@ to_ast_vga_connector(struct drm_connector *connector)
 
 struct ast_sil164_connector {
struct drm_connector base;
-   struct ast_i2c_chan *i2c;
 };
 
 static inline struct ast_sil164_connector *
diff --git a/drivers/gpu/drm/ast/ast_i2c.c b/drivers/gpu/drm/ast/ast_i2c.c
index 93e91c36d649..1d039ff1396e 100644
--- a/drivers/gpu/drm/ast/ast_i2c.c
+++ b/drivers/gpu/drm/ast/ast_i2c.c
@@ -117,7 +117,7 @@ struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev)
 
i2c = kzalloc(sizeof(struct ast_i2c_chan), GFP_KERNEL);
if (!i2c)
-   return NULL;
+   return ERR_PTR(-ENOMEM);
 
i2c->adapter.owner = THIS_MODULE;
i2c->adapter.class = I2C_CLASS_DDC;
@@ -143,10 +143,11 @@ struct ast_i2c_chan *ast_i2c_create(struct drm_device 
*dev)
 
ret = drmm_add_action_or_reset(dev, ast_i2c_release, i2c);
if (ret)
-   return NULL;
+   return ERR_PTR(ret);
+
return i2c;
 
 out_kfree:
kfree(i2c);
-   return NULL;
+   return ERR_PTR(ret);
 }
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index bbc566c4c768..5f273b5dd769 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -1334,19 +1334,18 @@ static int ast_vga_connector_init(struct drm_device 
*dev,
  struct ast_vga_connector *ast_vga_connector)
 {
struct drm_connector *connector = &ast_vga_connector->base;
+   struct ast_i2c_chan *i2c;
int ret;
 
-   ast_vga_connector->i2c = ast_i2c_create(dev);
-   if (!ast_vga_connector->i2c)
-   drm_err(dev, "failed to add ddc bus for connector\n");
+   i2c = ast_i2c_create(dev);
+   if (IS_ERR(i2c)) {
+   ret = PTR_ERR(i2c);
+   drm_err(dev, "failed to add ddc bus for connector; ret=%d\n", 
ret);
+   return ret;
+   }
 
-   if (ast_vga_connector->i2c)
-   ret = drm_connector_init_with_ddc(dev, connector, 
&ast_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA,
- 
&ast_vga_connector->i2c->adapter);
-   else
-   ret = drm_connector_init(dev, connector, 
&ast_vga_connector_funcs,
-DRM_MODE_CONNECTOR_VGA);
+   ret = drm_connector_init_with_ddc(dev, connector, 
&ast_vga_connector_funcs,
+ DRM_MODE_CONNECTOR_VGA, 
&i2c->adapter);
if (ret)
return ret;
 
@@ -1406,19 +1405,18 @@ static int ast_sil164_connector_init(struct drm_device 
*dev,
 struct ast_sil164_connector 
*ast_sil164_connector)
 {
struct drm_connector *connector = &ast_sil164_connector->base;
+   struct ast_i2c_chan *i2c;
int ret;
 
-   ast_sil164_connector->i2c = ast_i2c_create(dev);
-   if (!ast_sil164_connector->i2c)
-   drm_err(dev, "failed to add ddc bus for connector\n");
+   i2c = ast_i2c_create(dev);
+   if (IS_ERR(i2c)) {
+   ret = PTR_ERR(i2c);
+   drm_err(dev, "failed to add ddc bus for connector; ret=%d\n", 
ret);
+   return ret;
+   }
 
-   if (ast_sil164_connector->i2c)
-   ret = drm_connector_init_with_ddc(dev, connector, 
&ast_sil164_connector_funcs,
- DRM_MODE_CONNECTOR_DVII,
- 
&ast_sil164_connector->i2c->adapter);
-   else
-   ret = drm_connector_init(dev, connector, 
&ast_sil164_connector_funcs,
-DRM_MODE_CONNECTOR_DVII);
+   ret = drm_connector_init_with_ddc(dev, connector, 
&ast_sil164_connector_funcs,
+ DRM_MODE_CONNECTOR_DVII, 
&i2c->adapter);
if (ret)
return ret;
 
-- 
2.36.1



Re: [PATCH v2 0/5] drm/ast: Connector cleanups and polling

2022-05-31 Thread Thomas Zimmermann



Am 31.05.22 um 13:14 schrieb Thomas Zimmermann:

Various cleanups to ast's conenctor code. Simplifies the code, adds
support for using VGA and ASTDP connectors at the same time, and
initializes polling of the connector status.

Patch 1 was first posted at [1], so this patchset starts at version


[1] 
https://lore.kernel.org/dri-devel/20220510105010.20712-1-tzimmerm...@suse.de/



2. The implementation of detect_ctx in patch 3 has been added to DRM
helpers as it will be useful for other drivers, such as mgag200 and
udl.

Thomas Zimmermann (5):
   drm/ast: Support multiple outputs
   drm/ast: Fix updating the connector's EDID property
   drm/ast: Support output polling
   drm/ast: Fail probing if DCC channel could not be initialized
   drm/ast: Remove struct ast_{vga,sil164}_connector

  drivers/gpu/drm/ast/ast_dp.c   |   5 +-
  drivers/gpu/drm/ast/ast_dp501.c|   2 +-
  drivers/gpu/drm/ast/ast_drv.h  |  30 +-
  drivers/gpu/drm/ast/ast_i2c.c  |   7 +-
  drivers/gpu/drm/ast/ast_main.c |  21 ++--
  drivers/gpu/drm/ast/ast_mode.c | 165 ++---
  drivers/gpu/drm/ast/ast_post.c |   2 +-
  drivers/gpu/drm/drm_probe_helper.c |  35 ++
  include/drm/drm_probe_helper.h |   3 +
  9 files changed, 116 insertions(+), 154 deletions(-)


base-commit: 2c8cc5cd20e28afe6b63acb28890e5f57d9bf055


--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev


OpenPGP_signature
Description: OpenPGP digital signature


RE: [PATCH v3 0/2] Add RZ/G2L DSI driver

2022-05-31 Thread Biju Das
Hi All,

Gentle ping.

Are you ok with this patch series? Please let me know.

Cheers,
Biju

> Subject: [PATCH v3 0/2] Add RZ/G2L DSI driver
> 
> This patch series aims to support the MIPI DSI encoder found in the RZ/G2L
> SoC. It currently supports DSI mode only.
> 
> This unit supports MIPI Alliance Specification for Display Serial Interface
> (DSI) Specification. This unit provides a solution for transmitting MIPI
> DSI compliant digital video and packets. Normative References are below.
> * MIPI Alliance Specification for Display Serial Interface Version 1.3.1
> * MIPI Alliance Specification for D-PHY Version 2.1
> 
> The following are key features of this unit.
> 
> * 1 channel
> * The number of Lane: 4-lane
> * Support up to Full HD (1920 × 1080), 60 fps (RGB888)
> * Maximum Bandwidth: 1.5 Gbps per lane
> * Support Output Data Format: RGB666 / RGB888
> 
> v2->v3:
>  * Added Rb tag from Geert and Laurent for the binding patch.
>  * Fixed the typo "Receive" -> "transmit"
>  * Added accepible values for data-lanes
>  * Sorted Header file in the example
>  * Added SoC specific compaible along with generic one.
>  * pass rzg2l_mipi_dsi pointer to {Link,Phy} register rd/wr function
> instead
>of the memory pointer
>  * Fixed the comment in rzg2l_mipi_dsi_startup()
>  * Removed unnecessary dbg message from rzg2l_mipi_dsi_start_video()
>  * DRM bridge parameter initialization moved to probe
>  * Replaced dev_dbg->dev_err in rzg2l_mipi_dsi_parse_dt()
>  * Inserted the missing blank lane after return in probe()
>  * Added missing MODULE_DEVICE_TABLE
>  * Added include linux/bits.h in header file
>  * Fixed various macros in header file.
>  * Reorder the make file for DSI, so that it is no more dependent
>on RZ/G2L DU patch series.
> v1->v2:
>  * Added full path for dsi-controller.yaml
>  * Modeled DSI + D-PHY as single block and updated reg property
>  * Fixed typo D_PHY->D-PHY
>  * Updated description
>  * Added interrupts and interrupt-names and updated the example
>  * Driver rework based on dt-binding changes (DSI + D-PHY) as single block
>  * Replaced link_mmio and phy_mmio with mmio in struct rzg2l_mipi_dsi
>  * Replaced rzg2l_mipi_phy_write with rzg2l_mipi_dsi_phy_write
>and rzg2l_mipi_dsi_link_write
>  * Replaced rzg2l_mipi_phy_read->rzg2l_mipi_dsi_link_read
> RFC->v1:
>  * Added a ref to dsi-controller.yaml.
>  * Added "depends on ARCH_RENESAS || COMPILE_TEST" on KCONFIG
>and dropped DRM as it is implied by DRM_BRIDGE
>  * Used devm_reset_control_get_exclusive() for reset handle
>  * Removed bool hsclkmode from struct rzg2l_mipi_dsi
>  * Added error check for pm, using pm_runtime_resume_and_get() instead of
>pm_runtime_get_sync()
>  * Added check for unsupported formats in rzg2l_mipi_dsi_host_attach()
>  * Avoided read-modify-write stopping hsclock
>  * Used devm_platform_ioremap_resource for resource allocation
>  * Removed unnecessary assert call from probe and remove.
>  * wrap the line after the PTR_ERR() in probe()
>  * Updated reset failure messages in probe
>  * Fixed the typo arstc->prstc
>  * Made hex constants to lower case.
> RFC:
>  *
> 
> Biju Das (2):
>   dt-bindings: display: bridge: Document RZ/G2L MIPI DSI TX bindings
>   drm: rcar-du: Add RZ/G2L DSI driver
> 
>  .../bindings/display/bridge/renesas,dsi.yaml  | 182 +
>  drivers/gpu/drm/rcar-du/Kconfig   |   8 +
>  drivers/gpu/drm/rcar-du/Makefile  |   2 +
>  drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c  | 690 ++
>  drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h | 151 
>  5 files changed, 1033 insertions(+)
>  create mode 100644
> Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml
>  create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c
>  create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h
> 
> --
> 2.25.1



Re: [PATCH 2/7] dt-bindings: display: mediatek: dpi: add binding for MT8365

2022-05-31 Thread Krzysztof Kozlowski
On 30/05/2022 22:14, Fabien Parent wrote:
> DPI for MT8365 is compatible with MT8192 but requires an additional
> clock. Modify the documentation to requires this clock only on MT8365 SoCs.
> 
> Signed-off-by: Fabien Parent 
> ---
>  .../display/mediatek/mediatek,dpi.yaml| 44 ---
>  1 file changed, 37 insertions(+), 7 deletions(-)
> 
> diff --git 
> a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml 
> b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
> index caf4c88708f4..c9c9f4d5ebe7 100644
> --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
> +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
> @@ -17,13 +17,18 @@ description: |
>  
>  properties:
>compatible:
> -enum:
> -  - mediatek,mt2701-dpi
> -  - mediatek,mt7623-dpi
> -  - mediatek,mt8173-dpi
> -  - mediatek,mt8183-dpi
> -  - mediatek,mt8186-dpi
> -  - mediatek,mt8192-dpi
> +oneOf:
> +  - enum:
> +  - mediatek,mt2701-dpi
> +  - mediatek,mt7623-dpi
> +  - mediatek,mt8173-dpi
> +  - mediatek,mt8183-dpi
> +  - mediatek,mt8186-dpi
> +  - mediatek,mt8192-dpi
> +  - items:
> +  - enum:
> +  - mediatek,mt8365-dpi
> +  - const: mediatek,mt8192-dpi
>  
>reg:
>  maxItems: 1
> @@ -32,16 +37,20 @@ properties:
>  maxItems: 1
>  
>clocks:
> +minItems: 3
>  items:
>- description: Pixel Clock
>- description: Engine Clock
>- description: DPI PLL
> +  - description: DPI Clock
>  
>clock-names:
> +minItems: 3
>  items:
>- const: pixel
>- const: engine
>- const: pll
> +  - const: dpi
>  
>pinctrl-0: true
>pinctrl-1: true
> @@ -71,6 +80,27 @@ required:
>  
>  additionalProperties: false
>  
> +allOf:
> +  - if:
> +  properties:
> +compatible:
> +  contains:
> +const: mediatek,mt8365-dpi
> +
> +then:
> +  properties:
> +clocks:
> +  maxItems: 4
> +clock-names:
> +  maxItems: 4

These should be minItems instead.

> +
> +else:
> +  properties:
> +clocks:
> +  maxItems: 3
> +clock-names:
> +  maxItems: 3
> +
>  examples:
>- |
>  #include 


Best regards,
Krzysztof


[PATCH] drm/msm: less magic numbers in msm_mdss_enable

2022-05-31 Thread Dmitry Baryshkov
Replace magic register writes in msm_mdss_enable() with version that
contains less magic and more variable names that can be traced back to
the dpu_hw_catalog or the downstream dtsi files.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/msm_mdss.c | 79 ++
 1 file changed, 71 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index 0454a571adf7..2a48263cd1b5 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -21,6 +21,7 @@
 #define HW_REV 0x0
 #define HW_INTR_STATUS 0x0010
 
+#define UBWC_DEC_HW_VERSION0x58
 #define UBWC_STATIC0x144
 #define UBWC_CTRL_20x150
 #define UBWC_PREDICTION_MODE   0x154
@@ -132,9 +133,63 @@ static int _msm_mdss_irq_domain_add(struct msm_mdss 
*msm_mdss)
return 0;
 }
 
+#define UBWC_1_0 0x1000
+#define UBWC_2_0 0x2000
+#define UBWC_3_0 0x3000
+#define UBWC_4_0 0x4000
+
+static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss,
+  u32 ubwc_static)
+{
+   writel_relaxed(ubwc_static, msm_mdss->mmio + UBWC_STATIC);
+}
+
+static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss,
+  unsigned int ubwc_version,
+  u32 ubwc_swizzle,
+  u32 highest_bank_bit,
+  u32 macrotile_mode)
+{
+   u32 value = (ubwc_swizzle & 0x1) |
+   (highest_bank_bit & 0x3) << 4 |
+   (macrotile_mode & 0x1) << 12;
+
+   if (ubwc_version == UBWC_3_0)
+   value |= BIT(10);
+
+   if (ubwc_version == UBWC_1_0)
+   value |= BIT(8);
+
+   writel_relaxed(value, msm_mdss->mmio + UBWC_STATIC);
+}
+
+static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss,
+  unsigned int ubwc_version,
+  u32 ubwc_swizzle,
+  u32 ubwc_static,
+  u32 highest_bank_bit,
+  u32 macrotile_mode)
+{
+   u32 value = (ubwc_swizzle & 0x7) |
+   (ubwc_static & 0x1) << 3 |
+   (highest_bank_bit & 0x7) << 4 |
+   (macrotile_mode & 0x1) << 12;
+
+   writel_relaxed(value, msm_mdss->mmio + UBWC_STATIC);
+
+   if (ubwc_version == UBWC_3_0) {
+   writel_relaxed(1, msm_mdss->mmio + UBWC_CTRL_2);
+   writel_relaxed(0, msm_mdss->mmio + UBWC_PREDICTION_MODE);
+   } else {
+   writel_relaxed(2, msm_mdss->mmio + UBWC_CTRL_2);
+   writel_relaxed(1, msm_mdss->mmio + UBWC_PREDICTION_MODE);
+   }
+}
+
 static int msm_mdss_enable(struct msm_mdss *msm_mdss)
 {
int ret;
+   u32 hw_rev;
 
ret = clk_bulk_prepare_enable(msm_mdss->num_clocks, msm_mdss->clocks);
if (ret) {
@@ -149,26 +204,34 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss)
if (msm_mdss->is_mdp5)
return 0;
 
+   hw_rev = readl_relaxed(msm_mdss->mmio + HW_REV);
+   dev_info(msm_mdss->dev, "HW_REV: 0x%x\n", hw_rev);
+   dev_info(msm_mdss->dev, "UBWC_DEC_HW_VERSION: 0x%x\n",
+   readl_relaxed(msm_mdss->mmio + UBWC_DEC_HW_VERSION));
+
/*
 * ubwc config is part of the "mdss" region which is not accessible
 * from the rest of the driver. hardcode known configurations here
+*
+* Decoder version can be read from the UBWC_DEC_HW_VERSION reg,
+* UBWC_n comes from hw_catalog.
+* Unforunately this driver can not access hw catalog.
 */
-   switch (readl_relaxed(msm_mdss->mmio + HW_REV)) {
+   switch (hw_rev) {
case DPU_HW_VER_500:
case DPU_HW_VER_501:
-   writel_relaxed(0x420, msm_mdss->mmio + UBWC_STATIC);
+   msm_mdss_setup_ubwc_dec_30(msm_mdss, UBWC_3_0, 0, 2, 0);
break;
case DPU_HW_VER_600:
-   /* TODO: 0x102e for LP_DDR4 */
-   writel_relaxed(0x103e, msm_mdss->mmio + UBWC_STATIC);
-   writel_relaxed(2, msm_mdss->mmio + UBWC_CTRL_2);
-   writel_relaxed(1, msm_mdss->mmio + UBWC_PREDICTION_MODE);
+   /* TODO: highest_bank_bit = 2 for LP_DDR4 */
+   msm_mdss_setup_ubwc_dec_40(msm_mdss, UBWC_4_0, 6, 1, 3, 1);
break;
case DPU_HW_VER_620:
-   writel_relaxed(0x1e, msm_mdss->mmio + UBWC_STATIC);
+   /* UBWC_2_0 */
+   msm_mdss_setup_ubwc_dec_20(msm_mdss, 0x1e);
break;
case DPU_HW_VER_720:
-   writel_relaxed(0x101e, msm_mdss->mmio + UBWC_STATIC);
+   msm_mdss_setup_ubwc_dec_40(msm_mdss, UBWC_3_0, 6, 1, 1, 1);
  

Re: [PATCH] drm/prime: Ensure mmap offset is initialized

2022-05-31 Thread Daniel Vetter
On Mon, 30 May 2022 at 17:41, Rob Clark  wrote:
>
> On Mon, May 30, 2022 at 7:49 AM Daniel Vetter  wrote:
> >
> > On Mon, 30 May 2022 at 15:54, Rob Clark  wrote:
> > >
> > > On Mon, May 30, 2022 at 12:26 AM Thomas Zimmermann  
> > > wrote:
> > > >
> > > > Hi
> > > >
> > > > Am 29.05.22 um 18:29 schrieb Rob Clark:
> > > > > From: Rob Clark 
> > > > >
> > > > > If a GEM object is allocated, and then exported as a dma-buf fd which 
> > > > > is
> > > > > mmap'd before or without the GEM buffer being directly mmap'd, the
> > > > > vma_node could be unitialized.  This leads to a situation where the 
> > > > > CPU
> > > > > mapping is not correctly torn down in drm_vma_node_unmap().
> > > >
> > > > Which drivers are affected by this problem?
> > > >
> > > > I checked several drivers and most appear to be initializing the offset
> > > > during object construction, such as GEM SHMEM. [1] TTM-based drivers
> > > > also seem unaffected. [2]
> > > >
> > > >  From a quick grep, only etnaviv, msm and omapdrm appear to be affected?
> > > > They only seem to run drm_gem_create_mmap_offset() from their
> > > > ioctl-handling code.
> > > >
> > > > If so, I'd say it's preferable to fix these drivers and put a
> > > > drm_WARN_ONCE() into drm_gem_prime_mmap().
> > >
> > > That is good if fewer drivers are affected, however I disagree with
> > > your proposal.  At least for freedreno userspace, a lot of bo's never
> > > get mmap'd (either directly of via dmabuf), so we should not be
> > > allocating a mmap offset unnecessarily.
> >
> > Does this actually matter in the grand scheme of things? We originally
> > allocated mmap offset only on demand because userspace only had 32bit
> > loff_t support and so simply couldn't mmap anything if the offset
> > ended up above 32bit (even if there was still va space available).
> >
> > But those days are long gone (about 10 years or so) and the allocation
> > overhead for an mmap offset is tiny. So I think unless you can
> > benchmark an impact allocating it at bo alloc seems like the simplest
> > design overall, and hence what we should be doing. And if the vma
> > offset allocation every gets too slow due to fragmentation we can lift
> > the hole tree from i915 into drm_mm and the job should be done. At
> > that point we could also allocate the offset unconditionally in the
> > gem_init function and be done with it.
> >
> > Iow I concur with Thomas here, unless there's hard data contrary
> > simplicity imo trumps here.
>
> 32b userspace is still alive and well, at least on arm chromebooks ;-)

There's lots of different 32b userspace. The old thing was about
userspace which didn't use mmap64, but only mmap. Which could only
mmap the lower 4GB of a file, and so if you ended up with mmap_offset
above 4G then you'd blow up.

But mmap64 is a thing since forever, and if you compile with the right
glibc switch (loff_t is the magic thing iirc) it all works even with
default mmap. So I really don't think you should have this problem
anymore (except when cros is doing something really, really silly).
-Daniel

>
> BR,
> -R
>
> > -Daniel
> >
> > >
> > > BR,
> > > -R
> > >
> > > > Best regards
> > > > Thomas
> > > >
> > > > [1]
> > > > https://elixir.bootlin.com/linux/v5.18/source/drivers/gpu/drm/drm_gem_shmem_helper.c#L85
> > > > [2]
> > > > https://elixir.bootlin.com/linux/v5.18/source/drivers/gpu/drm/ttm/ttm_bo.c#L1002
> > > >
> > > > >
> > > > > Fixes: e5516553999f ("drm: call drm_gem_object_funcs.mmap with fake 
> > > > > offset")
> > > > > Signed-off-by: Rob Clark 
> > > > > ---
> > > > > Note, it's possible the issue existed in some related form prior to 
> > > > > the
> > > > > commit tagged with Fixes.
> > > > >
> > > > >   drivers/gpu/drm/drm_prime.c | 5 +
> > > > >   1 file changed, 5 insertions(+)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
> > > > > index e3f09f18110c..849eea154dfc 100644
> > > > > --- a/drivers/gpu/drm/drm_prime.c
> > > > > +++ b/drivers/gpu/drm/drm_prime.c
> > > > > @@ -716,6 +716,11 @@ int drm_gem_prime_mmap(struct drm_gem_object 
> > > > > *obj, struct vm_area_struct *vma)
> > > > >   struct file *fil;
> > > > >   int ret;
> > > > >
> > > > > + /* Ensure that the vma_node is initialized: */
> > > > > + ret = drm_gem_create_mmap_offset(obj);
> > > > > + if (ret)
> > > > > + return ret;
> > > > > +
> > > > >   /* Add the fake offset */
> > > > >   vma->vm_pgoff += drm_vma_node_start(&obj->vma_node);
> > > > >
> > > >
> > > > --
> > > > Thomas Zimmermann
> > > > Graphics Driver Developer
> > > > SUSE Software Solutions Germany GmbH
> > > > Maxfeldstr. 5, 90409 Nürnberg, Germany
> > > > (HRB 36809, AG Nürnberg)
> > > > Geschäftsführer: Ivo Totev
> >
> >
> >
> > --
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch



-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


Re: [PATCH 03/14] regulator: mt6370: Add mt6370 DisplayBias and VibLDO support

2022-05-31 Thread Mark Brown
On Tue, May 31, 2022 at 06:27:58PM +0800, ChiaEn Wu wrote:
> From: ChiYuan Huang 
> 
> Add mt6370 DisplayBias and VibLDO support.

Other than one small thing this looks nice and clean:

> + enable_gpio = fwnode_gpiod_get_index(of_fwnode_handle(np), "enable", 0,
> +  GPIOD_OUT_HIGH |
> +  GPIOD_FLAGS_BIT_NONEXCLUSIVE,
> +  desc->name);
> + if (IS_ERR(enable_gpio)) {
> + config->ena_gpiod = NULL;
> + return 0;
> + }

Please just use the OF APIs - due to ACPI's handling of power for
devices the regulator API OF bindings can't be used sensibly on
ACPI so it's better to explicitly work on DT only.  This won't
actually cause problems here but it's a bit clearer.


signature.asc
Description: PGP signature


Re: [PATCH 1/7] dt-bindings: display: mediatek: dpi: add power-domains property

2022-05-31 Thread Rob Herring
On Mon, 30 May 2022 22:14:30 +0200, Fabien Parent wrote:
> DPI is part of the display / multimedia block in MediaTek SoCs, and
> always have a power-domain (at least in the upstream device-trees).
> Add the power-domains property to the binding documentation.
> 
> Signed-off-by: Fabien Parent 
> ---
>  .../devicetree/bindings/display/mediatek/mediatek,dpi.yaml  | 6 ++
>  1 file changed, 6 insertions(+)
> 

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:
Error: 
Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.example.dts:29.35-36
 syntax error
FATAL ERROR: Unable to parse input tree
make[1]: *** [scripts/Makefile.lib:364: 
Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.example.dtb] 
Error 1
make[1]: *** Waiting for unfinished jobs
make: *** [Makefile:1401: dt_binding_check] Error 2

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: [RFC V3 0/2] Attach and Set vrr_enabled property

2022-05-31 Thread Daniel Vetter
On Tue, May 17, 2022 at 12:56:34PM +0530, Bhanuprakash Modem wrote:
> This series will add a support to set the vrr_enabled property for
> crtc based on the platform support and the request from userspace.
> And userspace can also query to get the status of "vrr_enabled".
> 
> Test-with: 20220422075223.2792586-2-bhanuprakash.mo...@intel.com
> 
> Bhanuprakash Modem (2):
>   drm/vrr: Attach vrr_enabled property to the drm crtc
>   drm/i915/vrr: Set drm crtc vrr_enabled property

I'm rather confused by this patch set:

- This seems to move the property from connector to crtc without any
  justification. For uapi that we want to have standardized (anything
  around kms really) that's no good, unless there's really a mandatory
  semantic reason pls stick to existing uapi.

- If the driver interface doesn't fit (maybe the helper should be on the
  crtc and adjust the property for all connector) pls roll that change out
  to all drivers.

- This is uapi, so needs igt tests and userspace. For igts we should make
  sure they're generic so that they apply across all drivers which already
  support this property, and not just create new intel-only testcases.

- Finally the property is set up, but not wired through. Or at least I'm
  not seeing how this can even work.

So no idea what exactly you're aiming for here and what kind of comments
you want, but this doesn't look like it's on the right path at all.

Cheers, Daniel


> 
>  drivers/gpu/drm/drm_crtc.c   | 26 
>  drivers/gpu/drm/drm_mode_config.c|  2 +-
>  drivers/gpu/drm/i915/display/intel_vrr.c |  8 
>  include/drm/drm_crtc.h   |  3 +++
>  4 files changed, 38 insertions(+), 1 deletion(-)
> 
> --
> 2.35.1
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


[PATCH] drm/msm/dpu: Move min BW request and full BW disable back to mdss

2022-05-31 Thread Douglas Anderson
In commit a670ff578f1f ("drm/msm/dpu: always use mdp device to scale
bandwidth") we fully moved interconnect stuff to the DPU driver. This
had no change for sc7180 but _did_ have an impact for other SoCs. It
made them match the sc7180 scheme.

Unfortunately, the sc7180 scheme seems like it was a bit broken.
Specifically the interconnect needs to be on for more than just the
DPU driver's AXI bus. In the very least it also needs to be on for the
DSI driver's AXI bus. This can be seen fairly easily by doing this on
a ChromeOS sc7180-trogdor class device:

  set_power_policy --ac_screen_dim_delay=5 --ac_screen_off_delay=10
  sleep 10
  cd /sys/bus/platform/devices/ae94000.dsi/power
  echo on > control

When you do that, you'll get a warning splat in the logs about
"gcc_disp_hf_axi_clk status stuck at 'off'".

One could argue that perhaps what I have done above is "illegal" and
that it can't happen naturally in the system because in normal system
usage the DPU is pretty much always on when DSI is on. That being
said:
* In official ChromeOS builds (admittedly a 5.4 kernel with backports)
  we have seen that splat at bootup.
* Even though we don't use "autosuspend" for these components, we
  don't use the "put_sync" variants. Thus plausibly the DSI could stay
  "runtime enabled" past when the DPU is enabled. Techncially we
  shouldn't do that if the DPU's suspend ends up yanking our clock.

Let's change things such that the "bare minimum" request for the
interconnect happens in the mdss driver again. That means that all of
the children can assume that the interconnect is on at the minimum
bandwidth. We'll then let the DPU request the higher amount that it
wants.

It should be noted that this isn't as hacky of a solution as it might
initially appear. Specifically:
* Since MDSS and DPU individually get their own references to the
  interconnect then the framework will actually handle aggregating
  them. The two drivers are _not_ clobbering each other.
* When the Qualcomm interconnect driver aggregates it takes the max of
  all the peaks. Thus having MDSS request a peak, as we're doing here,
  won't actually change the total interconnect bandwidth (it won't be
  added to the request for the DPU). This perhaps explains why the
  "average" requested in MDSS was historically 0 since that one
  _would_ be added in.

NOTE also that in the downstream ChromeOS 5.4 and 5.15 kernels, we're
also seeing some RPMH hangs that are addressed by this fix. These
hangs are showing up in the field and on _some_ devices with enough
stress testing of suspend/resume. Specifically right at suspend time
with a stack crawl that looks like this (from chromeos-5.15 tree):
  rpmh_write_batch+0x19c/0x240
  qcom_icc_bcm_voter_commit+0x210/0x420
  qcom_icc_set+0x28/0x38
  apply_constraints+0x70/0xa4
  icc_set_bw+0x150/0x24c
  dpu_runtime_resume+0x50/0x1c4
  pm_generic_runtime_resume+0x30/0x44
  __genpd_runtime_resume+0x68/0x7c
  genpd_runtime_resume+0x12c/0x20c
  __rpm_callback+0x98/0x138
  rpm_callback+0x30/0x88
  rpm_resume+0x370/0x4a0
  __pm_runtime_resume+0x80/0xb0
  dpu_kms_enable_commit+0x24/0x30
  msm_atomic_commit_tail+0x12c/0x630
  commit_tail+0xac/0x150
  drm_atomic_helper_commit+0x114/0x11c
  drm_atomic_commit+0x68/0x78
  drm_atomic_helper_disable_all+0x158/0x1c8
  drm_atomic_helper_suspend+0xc0/0x1c0
  drm_mode_config_helper_suspend+0x2c/0x60
  msm_pm_prepare+0x2c/0x40
  pm_generic_prepare+0x30/0x44
  genpd_prepare+0x80/0xd0
  device_prepare+0x78/0x17c
  dpm_prepare+0xb0/0x384
  dpm_suspend_start+0x34/0xc0

We don't completely understand all the mechanisms in play, but the
hang seemed to come and go with random factors. It's not terribly
surprising that the hang is gone after this patch since the line of
code that was failing is no longer present in the kernel.

Fixes: a670ff578f1f ("drm/msm/dpu: always use mdp device to scale bandwidth")
Fixes: c33b7c0389e1 ("drm/msm/dpu: add support for clk and bw scaling for 
display")
Signed-off-by: Douglas Anderson 
---

 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  8 
 drivers/gpu/drm/msm/msm_mdss.c  | 58 +
 2 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 2b9d931474e0..3025184053e0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -49,8 +49,6 @@
 #define DPU_DEBUGFS_DIR "msm_dpu"
 #define DPU_DEBUGFS_HWMASKNAME "hw_log_mask"
 
-#define MIN_IB_BW  4ULL /* Min ib vote 400MB */
-
 static int dpu_kms_hw_init(struct msm_kms *kms);
 static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms);
 
@@ -1303,15 +1301,9 @@ static int __maybe_unused dpu_runtime_resume(struct 
device *dev)
struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
struct drm_encoder *encoder;
struct drm_device *ddev;
-   int i;
 
ddev = dpu_kms->dev;
 
-   WARN_ON(!(dpu_kms->num_paths));
-   /* 

[PATCH 1/2] drm/meson: encoder_cvbs: Fix refcount leak in meson_encoder_cvbs_init

2022-05-31 Thread Miaoqian Lin
of_graph_get_remote_node() returns remote device nodepointer with
refcount incremented, we should use of_node_put() on it when done.
Add missing of_node_put() to avoid refcount leak.

Fixes: 318ba02cd8a8 ("drm/meson: encoder_cvbs: switch to bridge with 
ATTACH_NO_CONNECTOR")
Signed-off-by: Miaoqian Lin 
---
 drivers/gpu/drm/meson/meson_encoder_cvbs.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/meson/meson_encoder_cvbs.c 
b/drivers/gpu/drm/meson/meson_encoder_cvbs.c
index fd8db97ba8ba..8110a6e39320 100644
--- a/drivers/gpu/drm/meson/meson_encoder_cvbs.c
+++ b/drivers/gpu/drm/meson/meson_encoder_cvbs.c
@@ -238,6 +238,7 @@ int meson_encoder_cvbs_init(struct meson_drm *priv)
}
 
meson_encoder_cvbs->next_bridge = of_drm_find_bridge(remote);
+   of_node_put(remote);
if (!meson_encoder_cvbs->next_bridge) {
dev_err(priv->dev, "Failed to find CVBS Connector bridge\n");
return -EPROBE_DEFER;
-- 
2.25.1



[PATCH 2/2] drm/meson: encoder_hdmi: Fix refcount leak in meson_encoder_hdmi_init

2022-05-31 Thread Miaoqian Lin
of_graph_get_remote_node() returns remote device nodepointer with
refcount incremented, we should use of_node_put() on it when done.
Add missing of_node_put() to avoid refcount leak.

Fixes: e67f6037ae1b ("drm/meson: split out encoder from meson_dw_hdmi")
Signed-off-by: Miaoqian Lin 
---
 drivers/gpu/drm/meson/meson_encoder_hdmi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c 
b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
index 5e306de6f485..f3341458f8b7 100644
--- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
@@ -363,6 +363,7 @@ int meson_encoder_hdmi_init(struct meson_drm *priv)
}
 
meson_encoder_hdmi->next_bridge = of_drm_find_bridge(remote);
+   of_node_put(remote);
if (!meson_encoder_hdmi->next_bridge) {
dev_err(priv->dev, "Failed to find HDMI transceiver bridge\n");
return -EPROBE_DEFER;
-- 
2.25.1



Re: [PATCH] drm/prime: Ensure mmap offset is initialized

2022-05-31 Thread Rob Clark
On Tue, May 31, 2022 at 5:32 AM Daniel Vetter  wrote:
>
> On Mon, 30 May 2022 at 17:41, Rob Clark  wrote:
> >
> > On Mon, May 30, 2022 at 7:49 AM Daniel Vetter  wrote:
> > >
> > > On Mon, 30 May 2022 at 15:54, Rob Clark  wrote:
> > > >
> > > > On Mon, May 30, 2022 at 12:26 AM Thomas Zimmermann 
> > > >  wrote:
> > > > >
> > > > > Hi
> > > > >
> > > > > Am 29.05.22 um 18:29 schrieb Rob Clark:
> > > > > > From: Rob Clark 
> > > > > >
> > > > > > If a GEM object is allocated, and then exported as a dma-buf fd 
> > > > > > which is
> > > > > > mmap'd before or without the GEM buffer being directly mmap'd, the
> > > > > > vma_node could be unitialized.  This leads to a situation where the 
> > > > > > CPU
> > > > > > mapping is not correctly torn down in drm_vma_node_unmap().
> > > > >
> > > > > Which drivers are affected by this problem?
> > > > >
> > > > > I checked several drivers and most appear to be initializing the 
> > > > > offset
> > > > > during object construction, such as GEM SHMEM. [1] TTM-based drivers
> > > > > also seem unaffected. [2]
> > > > >
> > > > >  From a quick grep, only etnaviv, msm and omapdrm appear to be 
> > > > > affected?
> > > > > They only seem to run drm_gem_create_mmap_offset() from their
> > > > > ioctl-handling code.
> > > > >
> > > > > If so, I'd say it's preferable to fix these drivers and put a
> > > > > drm_WARN_ONCE() into drm_gem_prime_mmap().
> > > >
> > > > That is good if fewer drivers are affected, however I disagree with
> > > > your proposal.  At least for freedreno userspace, a lot of bo's never
> > > > get mmap'd (either directly of via dmabuf), so we should not be
> > > > allocating a mmap offset unnecessarily.
> > >
> > > Does this actually matter in the grand scheme of things? We originally
> > > allocated mmap offset only on demand because userspace only had 32bit
> > > loff_t support and so simply couldn't mmap anything if the offset
> > > ended up above 32bit (even if there was still va space available).
> > >
> > > But those days are long gone (about 10 years or so) and the allocation
> > > overhead for an mmap offset is tiny. So I think unless you can
> > > benchmark an impact allocating it at bo alloc seems like the simplest
> > > design overall, and hence what we should be doing. And if the vma
> > > offset allocation every gets too slow due to fragmentation we can lift
> > > the hole tree from i915 into drm_mm and the job should be done. At
> > > that point we could also allocate the offset unconditionally in the
> > > gem_init function and be done with it.
> > >
> > > Iow I concur with Thomas here, unless there's hard data contrary
> > > simplicity imo trumps here.
> >
> > 32b userspace is still alive and well, at least on arm chromebooks ;-)
>
> There's lots of different 32b userspace. The old thing was about
> userspace which didn't use mmap64, but only mmap. Which could only
> mmap the lower 4GB of a file, and so if you ended up with mmap_offset
> above 4G then you'd blow up.
>
> But mmap64 is a thing since forever, and if you compile with the right
> glibc switch (loff_t is the magic thing iirc) it all works even with
> default mmap. So I really don't think you should have this problem
> anymore (except when cros is doing something really, really silly).

The other thing, not sure quite how much it matters, is the
vma_offset_manager size is smaller with 32b kernels, which is still a
thing on some devices.

But at any rate, not allocating a mmap offset when it isn't needed
still seems like an eminently reasonable thing to do.  And IMO my fix
is quite reasonable too.  But if you disagree I can workaround the
core helpers in the driver.

BR,
-R

> -Daniel
>
> >
> > BR,
> > -R
> >
> > > -Daniel
> > >
> > > >
> > > > BR,
> > > > -R
> > > >
> > > > > Best regards
> > > > > Thomas
> > > > >
> > > > > [1]
> > > > > https://elixir.bootlin.com/linux/v5.18/source/drivers/gpu/drm/drm_gem_shmem_helper.c#L85
> > > > > [2]
> > > > > https://elixir.bootlin.com/linux/v5.18/source/drivers/gpu/drm/ttm/ttm_bo.c#L1002
> > > > >
> > > > > >
> > > > > > Fixes: e5516553999f ("drm: call drm_gem_object_funcs.mmap with fake 
> > > > > > offset")
> > > > > > Signed-off-by: Rob Clark 
> > > > > > ---
> > > > > > Note, it's possible the issue existed in some related form prior to 
> > > > > > the
> > > > > > commit tagged with Fixes.
> > > > > >
> > > > > >   drivers/gpu/drm/drm_prime.c | 5 +
> > > > > >   1 file changed, 5 insertions(+)
> > > > > >
> > > > > > diff --git a/drivers/gpu/drm/drm_prime.c 
> > > > > > b/drivers/gpu/drm/drm_prime.c
> > > > > > index e3f09f18110c..849eea154dfc 100644
> > > > > > --- a/drivers/gpu/drm/drm_prime.c
> > > > > > +++ b/drivers/gpu/drm/drm_prime.c
> > > > > > @@ -716,6 +716,11 @@ int drm_gem_prime_mmap(struct drm_gem_object 
> > > > > > *obj, struct vm_area_struct *vma)
> > > > > >   struct file *fil;
> > > > > >   int ret;
> > > > > >
> > > > > > + /* Ensure that the vma_node is initialized: */
> > > > > > + ret = 

Re: [PATCH] drm/ssd130x: Only define a SPI device ID table when built as a module

2022-05-31 Thread Nathan Chancellor
On Mon, May 30, 2022 at 04:02:46PM +0200, Javier Martinez Canillas wrote:
> The kernel test robot reports a compile warning due the ssd130x_spi_table
> variable being defined but not used. This happen when ssd130x-spi driver
> is built-in instead of being built as a module, i.e:
> 
>   CC  drivers/gpu/drm/solomon/ssd130x-spi.o
>   AR  drivers/base/firmware_loader/built-in.a
>   AR  drivers/base/built-in.a
>   CC  kernel/trace/trace.o
> drivers/gpu/drm/solomon/ssd130x-spi.c:155:35: warning: ‘ssd130x_spi_table’ 
> defined but not used [-Wunused-const-variable=]
>   155 | static const struct spi_device_id ssd130x_spi_table[] = {
>   |   ^
> 
> The driver shouldn't need a SPI device ID table and only have an OF device
> ID table, but the former is needed to workaround an issue in the SPI core.
> This always reports a MODALIAS of the form "spi:" even for devices
> registered through Device Trees.
> 
> But the table is only needed when the driver built as a module to populate
> the .ko alias info. It's not needed when the driver is built-in the kernel.
> 
> Fixes: 74373977d2ca ("drm/solomon: Add SSD130x OLED displays SPI support")
> Reported-by: kernel test robot 
> Signed-off-by: Javier Martinez Canillas 

Reviewed-by: Nathan Chancellor 

> ---
> 
>  drivers/gpu/drm/solomon/ssd130x-spi.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/gpu/drm/solomon/ssd130x-spi.c 
> b/drivers/gpu/drm/solomon/ssd130x-spi.c
> index 43722adab1f8..07802907e39a 100644
> --- a/drivers/gpu/drm/solomon/ssd130x-spi.c
> +++ b/drivers/gpu/drm/solomon/ssd130x-spi.c
> @@ -143,6 +143,7 @@ static const struct of_device_id ssd130x_of_match[] = {
>  };
>  MODULE_DEVICE_TABLE(of, ssd130x_of_match);
>  
> +#if IS_MODULE(CONFIG_DRM_SSD130X_SPI)
>  /*
>   * The SPI core always reports a MODALIAS uevent of the form "spi:", 
> even
>   * if the device was registered via OF. This means that the module will not 
> be
> @@ -160,6 +161,7 @@ static const struct spi_device_id ssd130x_spi_table[] = {
>   { /* sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(spi, ssd130x_spi_table);
> +#endif
>  
>  static struct spi_driver ssd130x_spi_driver = {
>   .driver = {
> -- 
> 2.36.1
> 


Re: [PATCH 3/6] drm/sun4i: sun8i-hdmi-phy: Used device-managed clocks/resets

2022-05-31 Thread Maxime Ripard
Hi Samuel,

Sorry for the (very) late answer

On Tue, Apr 12, 2022 at 06:34:40PM -0500, Samuel Holland wrote:
> On 4/12/22 8:23 AM, Maxime Ripard wrote:
> > Hi,
> > 
> > On Mon, Apr 11, 2022 at 11:35:08PM -0500, Samuel Holland wrote:
> >> Now that the HDMI PHY is using a platform driver, it can use device-
> >> managed resources. Use these, as well as the dev_err_probe helper, to
> >> simplify the probe function and get rid of the remove function.
> >>
> >> Signed-off-by: Samuel Holland 
> >> ---
> >>
> >>  drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 100 -
> >>  1 file changed, 30 insertions(+), 70 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
> >> b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> >> index 1effa30bfe62..1351e633d485 100644
> >> --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> >> +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> >> @@ -673,10 +673,8 @@ int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, 
> >> struct device_node *node)
> >>  static int sun8i_hdmi_phy_probe(struct platform_device *pdev)
> >>  {
> >>struct device *dev = &pdev->dev;
> >> -  struct device_node *node = dev->of_node;
> >>struct sun8i_hdmi_phy *phy;
> >>void __iomem *regs;
> >> -  int ret;
> >>  
> >>phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
> >>if (!phy)
> >> @@ -686,88 +684,50 @@ static int sun8i_hdmi_phy_probe(struct 
> >> platform_device *pdev)
> >>phy->dev = dev;
> >>  
> >>regs = devm_platform_ioremap_resource(pdev, 0);
> >> -  if (IS_ERR(regs)) {
> >> -  dev_err(dev, "Couldn't map the HDMI PHY registers\n");
> >> -  return PTR_ERR(regs);
> >> -  }
> >> +  if (IS_ERR(regs))
> >> +  return dev_err_probe(dev, PTR_ERR(regs),
> >> +   "Couldn't map the HDMI PHY registers\n");
> >>  
> >>phy->regs = devm_regmap_init_mmio(dev, regs,
> >>  &sun8i_hdmi_phy_regmap_config);
> >> -  if (IS_ERR(phy->regs)) {
> >> -  dev_err(dev, "Couldn't create the HDMI PHY regmap\n");
> >> -  return PTR_ERR(phy->regs);
> >> -  }
> >> +  if (IS_ERR(phy->regs))
> >> +  return dev_err_probe(dev, PTR_ERR(phy->regs),
> >> +   "Couldn't create the HDMI PHY regmap\n");
> >>  
> >> -  phy->clk_bus = of_clk_get_by_name(node, "bus");
> >> -  if (IS_ERR(phy->clk_bus)) {
> >> -  dev_err(dev, "Could not get bus clock\n");
> >> -  return PTR_ERR(phy->clk_bus);
> >> -  }
> >> -
> >> -  phy->clk_mod = of_clk_get_by_name(node, "mod");
> >> -  if (IS_ERR(phy->clk_mod)) {
> >> -  dev_err(dev, "Could not get mod clock\n");
> >> -  ret = PTR_ERR(phy->clk_mod);
> >> -  goto err_put_clk_bus;
> >> -  }
> >> +  phy->clk_bus = devm_clk_get(dev, "bus");
> >> +  if (IS_ERR(phy->clk_bus))
> >> +  return dev_err_probe(dev, PTR_ERR(phy->clk_bus),
> >> +   "Could not get bus clock\n");
> >>  
> >> -  if (phy->variant->has_phy_clk) {
> >> -  phy->clk_pll0 = of_clk_get_by_name(node, "pll-0");
> >> -  if (IS_ERR(phy->clk_pll0)) {
> >> -  dev_err(dev, "Could not get pll-0 clock\n");
> >> -  ret = PTR_ERR(phy->clk_pll0);
> >> -  goto err_put_clk_mod;
> >> -  }
> >> -
> >> -  if (phy->variant->has_second_pll) {
> >> -  phy->clk_pll1 = of_clk_get_by_name(node, "pll-1");
> >> -  if (IS_ERR(phy->clk_pll1)) {
> >> -  dev_err(dev, "Could not get pll-1 clock\n");
> >> -  ret = PTR_ERR(phy->clk_pll1);
> >> -  goto err_put_clk_pll0;
> >> -  }
> >> -  }
> >> -  }
> >> +  phy->clk_mod = devm_clk_get(dev, "mod");
> >> +  if (IS_ERR(phy->clk_mod))
> >> +  return dev_err_probe(dev, PTR_ERR(phy->clk_mod),
> >> +   "Could not get mod clock\n");
> >>  
> >> -  phy->rst_phy = of_reset_control_get_shared(node, "phy");
> >> -  if (IS_ERR(phy->rst_phy)) {
> >> -  dev_err(dev, "Could not get phy reset control\n");
> >> -  ret = PTR_ERR(phy->rst_phy);
> >> -  goto err_put_clk_pll1;
> >> -  }
> >> +  if (phy->variant->has_phy_clk)
> >> +  phy->clk_pll0 = devm_clk_get(dev, "pll-0");
> >> +  if (IS_ERR(phy->clk_pll0))
> >> +  return dev_err_probe(dev, PTR_ERR(phy->clk_pll0),
> >> +   "Could not get pll-0 clock\n");
> >> +
> >> +  if (phy->variant->has_second_pll)
> >> +  phy->clk_pll1 = devm_clk_get(dev, "pll-1");
> >> +  if (IS_ERR(phy->clk_pll1))
> >> +  return dev_err_probe(dev, PTR_ERR(phy->clk_pll1),
> >> +   "Could not get pll-1 clock\n");
> >> +
> >> +  phy->rst_phy = devm_reset_control_get_shared(dev, "phy");
> >> +  if (IS_ERR(phy->rst_phy))
> >> +  return dev_err_probe(dev, PTR_ERR(phy->rst_phy),
> >> +   "Could n

[PATCH v4 01/13] mm: add zone device coherent type memory support

2022-05-31 Thread Alex Sierra
Device memory that is cache coherent from device and CPU point of view.
This is used on platforms that have an advanced system bus (like CAPI
or CXL). Any page of a process can be migrated to such memory. However,
no one should be allowed to pin such memory so that it can always be
evicted.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
Reviewed-by: Alistair Popple 
[hch: rebased ontop of the refcount changes,
  removed is_dev_private_or_coherent_page]
Signed-off-by: Christoph Hellwig 
---
 include/linux/memremap.h | 19 +++
 mm/memcontrol.c  |  7 ---
 mm/memory-failure.c  |  8 ++--
 mm/memremap.c| 10 ++
 mm/migrate_device.c  | 16 +++-
 mm/rmap.c|  5 +++--
 6 files changed, 49 insertions(+), 16 deletions(-)

diff --git a/include/linux/memremap.h b/include/linux/memremap.h
index 8af304f6b504..9f752ebed613 100644
--- a/include/linux/memremap.h
+++ b/include/linux/memremap.h
@@ -41,6 +41,13 @@ struct vmem_altmap {
  * A more complete discussion of unaddressable memory may be found in
  * include/linux/hmm.h and Documentation/vm/hmm.rst.
  *
+ * MEMORY_DEVICE_COHERENT:
+ * Device memory that is cache coherent from device and CPU point of view. This
+ * is used on platforms that have an advanced system bus (like CAPI or CXL). A
+ * driver can hotplug the device memory using ZONE_DEVICE and with that memory
+ * type. Any page of a process can be migrated to such memory. However no one
+ * should be allowed to pin such memory so that it can always be evicted.
+ *
  * MEMORY_DEVICE_FS_DAX:
  * Host memory that has similar access semantics as System RAM i.e. DMA
  * coherent and supports page pinning. In support of coordinating page
@@ -61,6 +68,7 @@ struct vmem_altmap {
 enum memory_type {
/* 0 is reserved to catch uninitialized type fields */
MEMORY_DEVICE_PRIVATE = 1,
+   MEMORY_DEVICE_COHERENT,
MEMORY_DEVICE_FS_DAX,
MEMORY_DEVICE_GENERIC,
MEMORY_DEVICE_PCI_P2PDMA,
@@ -143,6 +151,17 @@ static inline bool folio_is_device_private(const struct 
folio *folio)
return is_device_private_page(&folio->page);
 }
 
+static inline bool is_device_coherent_page(const struct page *page)
+{
+   return is_zone_device_page(page) &&
+   page->pgmap->type == MEMORY_DEVICE_COHERENT;
+}
+
+static inline bool folio_is_device_coherent(const struct folio *folio)
+{
+   return is_device_coherent_page(&folio->page);
+}
+
 static inline bool is_pci_p2pdma_page(const struct page *page)
 {
return IS_ENABLED(CONFIG_PCI_P2PDMA) &&
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index abec50f31fe6..93f80d7ca148 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -5665,8 +5665,8 @@ static int mem_cgroup_move_account(struct page *page,
  *   2(MC_TARGET_SWAP): if the swap entry corresponding to this pte is a
  * target for charge migration. if @target is not NULL, the entry is stored
  * in target->ent.
- *   3(MC_TARGET_DEVICE): like MC_TARGET_PAGE  but page is 
MEMORY_DEVICE_PRIVATE
- * (so ZONE_DEVICE page and thus not on the lru).
+ *   3(MC_TARGET_DEVICE): like MC_TARGET_PAGE  but page is device memory and
+ *   thus not on the lru.
  * For now we such page is charge like a regular page would be as for all
  * intent and purposes it is just special memory taking the place of a
  * regular page.
@@ -5704,7 +5704,8 @@ static enum mc_target_type get_mctgt_type(struct 
vm_area_struct *vma,
 */
if (page_memcg(page) == mc.from) {
ret = MC_TARGET_PAGE;
-   if (is_device_private_page(page))
+   if (is_device_private_page(page) ||
+   is_device_coherent_page(page))
ret = MC_TARGET_DEVICE;
if (target)
target->page = page;
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index b85661cbdc4a..0b6a0a01ee09 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1683,12 +1683,16 @@ static int memory_failure_dev_pagemap(unsigned long 
pfn, int flags,
goto unlock;
}
 
-   if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
+   switch (pgmap->type) {
+   case MEMORY_DEVICE_PRIVATE:
+   case MEMORY_DEVICE_COHERENT:
/*
-* TODO: Handle HMM pages which may need coordination
+* TODO: Handle device pages which may need coordination
 * with device-side memory.
 */
goto unlock;
+   default:
+   break;
}
 
/*
diff --git a/mm/memremap.c b/mm/memremap.c
index 2b92e97cb25b..dbd2631b3520 100644
--- a/mm/memremap.c
+++ b/mm/memremap.c
@@ -315,6 +315,16 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
return ERR_PTR(-EINVAL);
}
break;

[PATCH v4 03/13] mm: add device coherent vma selection for memory migration

2022-05-31 Thread Alex Sierra
This case is used to migrate pages from device memory, back to system
memory. Device coherent type memory is cache coherent from device and CPU
point of view.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
Reviewed-by: Alistair Poppple 
Signed-off-by: Christoph Hellwig 
---
 include/linux/migrate.h |  1 +
 mm/migrate_device.c | 12 +---
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index 069a89e847f3..b84908debe5c 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -148,6 +148,7 @@ static inline unsigned long migrate_pfn(unsigned long pfn)
 enum migrate_vma_direction {
MIGRATE_VMA_SELECT_SYSTEM = 1 << 0,
MIGRATE_VMA_SELECT_DEVICE_PRIVATE = 1 << 1,
+   MIGRATE_VMA_SELECT_DEVICE_COHERENT = 1 << 2,
 };
 
 struct migrate_vma {
diff --git a/mm/migrate_device.c b/mm/migrate_device.c
index a4847ad65da3..18bc6483f63a 100644
--- a/mm/migrate_device.c
+++ b/mm/migrate_device.c
@@ -148,15 +148,21 @@ static int migrate_vma_collect_pmd(pmd_t *pmdp,
if (is_writable_device_private_entry(entry))
mpfn |= MIGRATE_PFN_WRITE;
} else {
-   if (!(migrate->flags & MIGRATE_VMA_SELECT_SYSTEM))
-   goto next;
pfn = pte_pfn(pte);
-   if (is_zero_pfn(pfn)) {
+   if (is_zero_pfn(pfn) &&
+   (migrate->flags & MIGRATE_VMA_SELECT_SYSTEM)) {
mpfn = MIGRATE_PFN_MIGRATE;
migrate->cpages++;
goto next;
}
page = vm_normal_page(migrate->vma, addr, pte);
+   if (page && !is_zone_device_page(page) &&
+   !(migrate->flags & MIGRATE_VMA_SELECT_SYSTEM))
+   goto next;
+   else if (page && is_device_coherent_page(page) &&
+   (!(migrate->flags & 
MIGRATE_VMA_SELECT_DEVICE_COHERENT) ||
+page->pgmap->owner != migrate->pgmap_owner))
+   goto next;
mpfn = migrate_pfn(pfn) | MIGRATE_PFN_MIGRATE;
mpfn |= pte_write(pte) ? MIGRATE_PFN_WRITE : 0;
}
-- 
2.32.0



[PATCH v4 02/13] mm: handling Non-LRU pages returned by vm_normal_pages

2022-05-31 Thread Alex Sierra
With DEVICE_COHERENT, we'll soon have vm_normal_pages() return
device-managed anonymous pages that are not LRU pages. Although they
behave like normal pages for purposes of mapping in CPU page, and for
COW. They do not support LRU lists, NUMA migration or THP.

We also introduced a FOLL_LRU flag that adds the same behaviour to
follow_page and related APIs, to allow callers to specify that they
expect to put pages on an LRU list.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
---
 fs/proc/task_mmu.c | 2 +-
 include/linux/mm.h | 3 ++-
 mm/gup.c   | 6 +-
 mm/huge_memory.c   | 2 +-
 mm/khugepaged.c| 9 ++---
 mm/ksm.c   | 6 +++---
 mm/madvise.c   | 4 ++--
 mm/memory.c| 9 -
 mm/mempolicy.c | 2 +-
 mm/migrate.c   | 4 ++--
 mm/mlock.c | 2 +-
 mm/mprotect.c  | 2 +-
 12 files changed, 33 insertions(+), 18 deletions(-)

diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 2d04e3470d4c..2dd8c8a66924 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1792,7 +1792,7 @@ static struct page *can_gather_numa_stats(pte_t pte, 
struct vm_area_struct *vma,
return NULL;
 
page = vm_normal_page(vma, addr, pte);
-   if (!page)
+   if (!page || is_zone_device_page(page))
return NULL;
 
if (PageReserved(page))
diff --git a/include/linux/mm.h b/include/linux/mm.h
index bc8f326be0ce..d3f43908ff8d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -601,7 +601,7 @@ struct vm_operations_struct {
 #endif
/*
 * Called by vm_normal_page() for special PTEs to find the
-* page for @addr.  This is useful if the default behavior
+* page for @addr. This is useful if the default behavior
 * (using pte_page()) would not find the correct page.
 */
struct page *(*find_special_page)(struct vm_area_struct *vma,
@@ -2934,6 +2934,7 @@ struct page *follow_page(struct vm_area_struct *vma, 
unsigned long address,
 #define FOLL_NUMA  0x200   /* force NUMA hinting page fault */
 #define FOLL_MIGRATION 0x400   /* wait for page to replace migration entry */
 #define FOLL_TRIED 0x800   /* a retry, previous pass started an IO */
+#define FOLL_LRU0x1000  /* return only LRU (anon or page cache) */
 #define FOLL_REMOTE0x2000  /* we are working on non-current tsk/mm */
 #define FOLL_COW   0x4000  /* internal GUP flag */
 #define FOLL_ANON  0x8000  /* don't do file mappings */
diff --git a/mm/gup.c b/mm/gup.c
index 551264407624..48b45bcc8501 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -532,7 +532,11 @@ static struct page *follow_page_pte(struct vm_area_struct 
*vma,
}
 
page = vm_normal_page(vma, address, pte);
-   if (!page && pte_devmap(pte) && (flags & (FOLL_GET | FOLL_PIN))) {
+   if ((flags & FOLL_LRU) && ((page && is_zone_device_page(page)) ||
+   (!page && pte_devmap(pte {
+   page = ERR_PTR(-EEXIST);
+   goto out;
+   } else if (!page && pte_devmap(pte) && (flags & (FOLL_GET | FOLL_PIN))) 
{
/*
 * Only return device mapping pages in the FOLL_GET or FOLL_PIN
 * case since they are only valid while holding the pgmap
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index a77c78a2b6b5..48182c8fe151 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2906,7 +2906,7 @@ static int split_huge_pages_pid(int pid, unsigned long 
vaddr_start,
}
 
/* FOLL_DUMP to ignore special (like zero) pages */
-   page = follow_page(vma, addr, FOLL_GET | FOLL_DUMP);
+   page = follow_page(vma, addr, FOLL_GET | FOLL_DUMP | FOLL_LRU);
 
if (IS_ERR(page))
continue;
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 16be62d493cd..671ac7800e53 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -618,7 +618,7 @@ static int __collapse_huge_page_isolate(struct 
vm_area_struct *vma,
goto out;
}
page = vm_normal_page(vma, address, pteval);
-   if (unlikely(!page)) {
+   if (unlikely(!page) || unlikely(is_zone_device_page(page))) {
result = SCAN_PAGE_NULL;
goto out;
}
@@ -1267,7 +1267,7 @@ static int khugepaged_scan_pmd(struct mm_struct *mm,
writable = true;
 
page = vm_normal_page(vma, _address, pteval);
-   if (unlikely(!page)) {
+   if (unlikely(!page) || unlikely(is_zone_device_page(page))) {
result = SCAN_PAGE_NULL;
goto out_unmap;
}
@@ -1479,7 +1479,8 @@ void collapse_pte_mapped_thp(struct mm_struct *mm, 
unsigned long addr)
goto abort;
 
page = vm_normal_page(vma, addr, *pte);
-
+   if (WARN_ON_ONCE(page && is_zone_device_p

[PATCH v4 04/13] mm: remove the vma check in migrate_vma_setup()

2022-05-31 Thread Alex Sierra
From: Alistair Popple 

migrate_vma_setup() checks that a valid vma is passed so that the page
tables can be walked to find the pfns associated with a given address
range. However in some cases the pfns are already known, such as when
migrating device coherent pages during pin_user_pages() meaning a valid
vma isn't required.

Signed-off-by: Alistair Popple 
Acked-by: Felix Kuehling 
Signed-off-by: Christoph Hellwig 
---
 mm/migrate_device.c | 34 +-
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/mm/migrate_device.c b/mm/migrate_device.c
index 18bc6483f63a..cf9668376c5a 100644
--- a/mm/migrate_device.c
+++ b/mm/migrate_device.c
@@ -486,24 +486,24 @@ int migrate_vma_setup(struct migrate_vma *args)
 
args->start &= PAGE_MASK;
args->end &= PAGE_MASK;
-   if (!args->vma || is_vm_hugetlb_page(args->vma) ||
-   (args->vma->vm_flags & VM_SPECIAL) || vma_is_dax(args->vma))
-   return -EINVAL;
-   if (nr_pages <= 0)
-   return -EINVAL;
-   if (args->start < args->vma->vm_start ||
-   args->start >= args->vma->vm_end)
-   return -EINVAL;
-   if (args->end <= args->vma->vm_start || args->end > args->vma->vm_end)
-   return -EINVAL;
if (!args->src || !args->dst)
return -EINVAL;
-
-   memset(args->src, 0, sizeof(*args->src) * nr_pages);
-   args->cpages = 0;
-   args->npages = 0;
-
-   migrate_vma_collect(args);
+   if (args->vma) {
+   if (is_vm_hugetlb_page(args->vma) ||
+   (args->vma->vm_flags & VM_SPECIAL) || vma_is_dax(args->vma))
+   return -EINVAL;
+   if (args->start < args->vma->vm_start ||
+   args->start >= args->vma->vm_end)
+   return -EINVAL;
+   if (args->end <= args->vma->vm_start ||
+   args->end > args->vma->vm_end)
+   return -EINVAL;
+   memset(args->src, 0, sizeof(*args->src) * nr_pages);
+   args->cpages = 0;
+   args->npages = 0;
+
+   migrate_vma_collect(args);
+   }
 
if (args->cpages)
migrate_vma_unmap(args);
@@ -685,7 +685,7 @@ void migrate_vma_pages(struct migrate_vma *migrate)
continue;
}
 
-   if (!page) {
+   if (!page && migrate->vma) {
if (!(migrate->src[i] & MIGRATE_PFN_MIGRATE))
continue;
if (!notified) {
-- 
2.32.0



[PATCH v4 00/13] Add MEMORY_DEVICE_COHERENT for coherent device memory mapping

2022-05-31 Thread Alex Sierra
This is our MEMORY_DEVICE_COHERENT patch series rebased and updated
for current 5.18.0

Changes since the last version:
- Fixed problems with migration during long-term pinning in
get_user_pages
- Open coded vm_normal_lru_pages as suggested in previous code review
- Update hmm_gup_test with more get_user_pages calls, include
hmm_cow_in_device in hmm-test.

This patch series introduces MEMORY_DEVICE_COHERENT, a type of memory
owned by a device that can be mapped into CPU page tables like
MEMORY_DEVICE_GENERIC and can also be migrated like
MEMORY_DEVICE_PRIVATE.

This patch series is mostly self-contained except for a few places where
it needs to update other subsystems to handle the new memory type.

System stability and performance are not affected according to our
ongoing testing, including xfstests.

How it works: The system BIOS advertises the GPU device memory
(aka VRAM) as SPM (special purpose memory) in the UEFI system address
map.

The amdgpu driver registers the memory with devmap as
MEMORY_DEVICE_COHERENT using devm_memremap_pages. The initial user for
this hardware page migration capability is the Frontier supercomputer
project. This functionality is not AMD-specific. We expect other GPU
vendors to find this functionality useful, and possibly other hardware
types in the future.

Our test nodes in the lab are similar to the Frontier configuration,
with .5 TB of system memory plus 256 GB of device memory split across
4 GPUs, all in a single coherent address space. Page migration is
expected to improve application efficiency significantly. We will
report empirical results as they become available.

Coherent device type pages at gup are now migrated back to system
memory if they are being pinned long-term (FOLL_LONGTERM). The reason
is, that long-term pinning would interfere with the device memory
manager owning the device-coherent pages (e.g. evictions in TTM).
These series incorporate Alistair Popple patches to do this
migration from pin_user_pages() calls. hmm_gup_test has been added to
hmm-test to test different get user pages calls.

This series includes handling of device-managed anonymous pages
returned by vm_normal_pages. Although they behave like normal pages
for purposes of mapping in CPU page tables and for COW, they do not
support LRU lists, NUMA migration or THP.

We also introduced a FOLL_LRU flag that adds the same behaviour to
follow_page and related APIs, to allow callers to specify that they
expect to put pages on an LRU list.

v2:
- Rebase to latest 5.18-rc7.
- Drop patch "mm: add device coherent checker to remove migration pte"
and modify try_to_migrate_one, to let DEVICE_COHERENT pages fall
through to normal page path. Based on Alistair Popple's comment.
- Fix comment formatting.
- Reword comment in vm_normal_page about pte_devmap().
- Merge "drm/amdkfd: coherent type as sys mem on migration to ram" to
"drm/amdkfd: add SPM support for SVM".

v3:
- Rebase to latest 5.18.0.
- Patch "mm: handling Non-LRU pages returned by vm_normal_pages"
reordered.
- Add WARN_ON_ONCE for thp device coherent case.

v4:
- Rebase to latest 5.18.0
- Fix consitency between pages with FOLL_LRU flag set and pte_devmap
at follow_page_pte.

Alex Sierra (11):
  mm: add zone device coherent type memory support
  mm: handling Non-LRU pages returned by vm_normal_pages
  mm: add device coherent vma selection for memory migration
  drm/amdkfd: add SPM support for SVM
  lib: test_hmm add ioctl to get zone device type
  lib: test_hmm add module param for zone device type
  lib: add support for device coherent type in test_hmm
  tools: update hmm-test to support device coherent type
  tools: update test_hmm script to support SP config
  tools: add hmm gup tests for device coherent type
  tools: add selftests to hmm for COW in device memory

Alistair Popple (2):
  mm: remove the vma check in migrate_vma_setup()
  mm/gup: migrate device coherent pages when pinning instead of failing

 drivers/gpu/drm/amd/amdkfd/kfd_migrate.c |  34 ++-
 fs/proc/task_mmu.c   |   2 +-
 include/linux/memremap.h |  19 ++
 include/linux/migrate.h  |   1 +
 include/linux/mm.h   |   3 +-
 lib/test_hmm.c   | 349 +--
 lib/test_hmm_uapi.h  |  22 +-
 mm/gup.c |  53 +++-
 mm/huge_memory.c |   2 +-
 mm/internal.h|   1 +
 mm/khugepaged.c  |   9 +-
 mm/ksm.c |   6 +-
 mm/madvise.c |   4 +-
 mm/memcontrol.c  |   7 +-
 mm/memory-failure.c  |   8 +-
 mm/memory.c  |   9 +-
 mm/mempolicy.c   |   2 +-
 mm/memremap.c|  10 +
 mm/migrate.c |   4 +-
 mm/migrate_device.c  | 115 ++--
 mm/mlo

[PATCH v4 06/13] drm/amdkfd: add SPM support for SVM

2022-05-31 Thread Alex Sierra
When CPU is connected throug XGMI, it has coherent
access to VRAM resource. In this case that resource
is taken from a table in the device gmc aperture base.
This resource is used along with the device type, which could
be DEVICE_PRIVATE or DEVICE_COHERENT to create the device
page map region.
Also, MIGRATE_VMA_SELECT_DEVICE_COHERENT flag is selected for
coherent type case during migration to device.

Signed-off-by: Alex Sierra 
Reviewed-by: Felix Kuehling 
Signed-off-by: Christoph Hellwig 
---
 drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 34 +++-
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 997650d597ec..39b8c4710caf 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -671,13 +671,15 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct 
svm_range *prange,
migrate.vma = vma;
migrate.start = start;
migrate.end = end;
-   migrate.flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
migrate.pgmap_owner = SVM_ADEV_PGMAP_OWNER(adev);
+   if (adev->gmc.xgmi.connected_to_cpu)
+   migrate.flags = MIGRATE_VMA_SELECT_DEVICE_COHERENT;
+   else
+   migrate.flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
 
buf = kvcalloc(npages,
   2 * sizeof(*migrate.src) + sizeof(uint64_t) + 
sizeof(dma_addr_t),
   GFP_KERNEL);
-
if (!buf)
goto out;
 
@@ -947,7 +949,7 @@ int svm_migrate_init(struct amdgpu_device *adev)
 {
struct kfd_dev *kfddev = adev->kfd.dev;
struct dev_pagemap *pgmap;
-   struct resource *res;
+   struct resource *res = NULL;
unsigned long size;
void *r;
 
@@ -962,28 +964,34 @@ int svm_migrate_init(struct amdgpu_device *adev)
 * should remove reserved size
 */
size = ALIGN(adev->gmc.real_vram_size, 2ULL << 20);
-   res = devm_request_free_mem_region(adev->dev, &iomem_resource, size);
-   if (IS_ERR(res))
-   return -ENOMEM;
+   if (adev->gmc.xgmi.connected_to_cpu) {
+   pgmap->range.start = adev->gmc.aper_base;
+   pgmap->range.end = adev->gmc.aper_base + adev->gmc.aper_size - 
1;
+   pgmap->type = MEMORY_DEVICE_COHERENT;
+   } else {
+   res = devm_request_free_mem_region(adev->dev, &iomem_resource, 
size);
+   if (IS_ERR(res))
+   return -ENOMEM;
+   pgmap->range.start = res->start;
+   pgmap->range.end = res->end;
+   pgmap->type = MEMORY_DEVICE_PRIVATE;
+   }
 
-   pgmap->type = MEMORY_DEVICE_PRIVATE;
pgmap->nr_range = 1;
-   pgmap->range.start = res->start;
-   pgmap->range.end = res->end;
pgmap->ops = &svm_migrate_pgmap_ops;
pgmap->owner = SVM_ADEV_PGMAP_OWNER(adev);
-   pgmap->flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
-
+   pgmap->flags = 0;
/* Device manager releases device-specific resources, memory region and
 * pgmap when driver disconnects from device.
 */
r = devm_memremap_pages(adev->dev, pgmap);
if (IS_ERR(r)) {
pr_err("failed to register HMM device memory\n");
-
/* Disable SVM support capability */
pgmap->type = 0;
-   devm_release_mem_region(adev->dev, res->start, 
resource_size(res));
+   if (pgmap->type == MEMORY_DEVICE_PRIVATE)
+   devm_release_mem_region(adev->dev, res->start,
+   res->end - res->start + 1);
return PTR_ERR(r);
}
 
-- 
2.32.0



[PATCH v4 05/13] mm/gup: migrate device coherent pages when pinning instead of failing

2022-05-31 Thread Alex Sierra
From: Alistair Popple 

Currently any attempts to pin a device coherent page will fail. This is
because device coherent pages need to be managed by a device driver, and
pinning them would prevent a driver from migrating them off the device.

However this is no reason to fail pinning of these pages. These are
coherent and accessible from the CPU so can be migrated just like
pinning ZONE_MOVABLE pages. So instead of failing all attempts to pin
them first try migrating them out of ZONE_DEVICE.

Signed-off-by: Alistair Popple 
Acked-by: Felix Kuehling 
[hch: rebased to the split device memory checks,
  moved migrate_device_page to migrate_device.c]
Signed-off-by: Christoph Hellwig 
---
 mm/gup.c| 47 +++-
 mm/internal.h   |  1 +
 mm/migrate_device.c | 53 +
 3 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/mm/gup.c b/mm/gup.c
index 48b45bcc8501..e6093c31f932 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1895,9 +1895,43 @@ static long check_and_migrate_movable_pages(unsigned 
long nr_pages,
continue;
prev_folio = folio;
 
-   if (folio_is_pinnable(folio))
+   /*
+* Device private pages will get faulted in during gup so it
+* shouldn't be possible to see one here.
+*/
+   if (WARN_ON_ONCE(folio_is_device_private(folio))) {
+   ret = -EFAULT;
+   goto unpin_pages;
+   }
+
+   /*
+* Device coherent pages are managed by a driver and should not
+* be pinned indefinitely as it prevents the driver moving the
+* page. So when trying to pin with FOLL_LONGTERM instead try
+* to migrate the page out of device memory.
+*/
+   if (folio_is_device_coherent(folio)) {
+   WARN_ON_ONCE(PageCompound(&folio->page));
+
+   /*
+* Migration will fail if the page is pinned, so convert
+* the pin on the source page to a normal reference.
+*/
+   if (gup_flags & FOLL_PIN) {
+   get_page(&folio->page);
+   unpin_user_page(&folio->page);
+   }
+
+   pages[i] = migrate_device_page(&folio->page, gup_flags);
+   if (!pages[i]) {
+   ret = -EBUSY;
+   goto unpin_pages;
+   }
continue;
+   }
 
+   if (folio_is_pinnable(folio))
+   continue;
/*
 * Try to move out any movable page before pinning the range.
 */
@@ -1933,10 +1967,13 @@ static long check_and_migrate_movable_pages(unsigned 
long nr_pages,
return nr_pages;
 
 unpin_pages:
-   if (gup_flags & FOLL_PIN) {
-   unpin_user_pages(pages, nr_pages);
-   } else {
-   for (i = 0; i < nr_pages; i++)
+   for (i = 0; i < nr_pages; i++) {
+   if (!pages[i])
+   continue;
+
+   if (gup_flags & FOLL_PIN)
+   unpin_user_page(pages[i]);
+   else
put_page(pages[i]);
}
 
diff --git a/mm/internal.h b/mm/internal.h
index c0f8fbe0445b..eeab4ee7a4a3 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -853,6 +853,7 @@ int numa_migrate_prep(struct page *page, struct 
vm_area_struct *vma,
  unsigned long addr, int page_nid, int *flags);
 
 void free_zone_device_page(struct page *page);
+struct page *migrate_device_page(struct page *page, unsigned int gup_flags);
 
 /*
  * mm/gup.c
diff --git a/mm/migrate_device.c b/mm/migrate_device.c
index cf9668376c5a..5decd26dd551 100644
--- a/mm/migrate_device.c
+++ b/mm/migrate_device.c
@@ -794,3 +794,56 @@ void migrate_vma_finalize(struct migrate_vma *migrate)
}
 }
 EXPORT_SYMBOL(migrate_vma_finalize);
+
+/*
+ * Migrate a device coherent page back to normal memory.  The caller should 
have
+ * a reference on page which will be copied to the new page if migration is
+ * successful or dropped on failure.
+ */
+struct page *migrate_device_page(struct page *page, unsigned int gup_flags)
+{
+   unsigned long src_pfn, dst_pfn = 0;
+   struct migrate_vma args;
+   struct page *dpage;
+
+   lock_page(page);
+   src_pfn = migrate_pfn(page_to_pfn(page)) | MIGRATE_PFN_MIGRATE;
+   args.src = &src_pfn;
+   args.dst = &dst_pfn;
+   args.cpages = 1;
+   args.npages = 1;
+   args.vma = NULL;
+   migrate_vma_setup(&args);
+   if (!(src_pfn & MIGRATE_PFN_MIGRATE))
+   return NULL;
+
+   dpage = alloc_pages(GFP_USER | __GFP_NOWARN, 0);
+

[PATCH v4 07/13] lib: test_hmm add ioctl to get zone device type

2022-05-31 Thread Alex Sierra
new ioctl cmd added to query zone device type. This will be
used once the test_hmm adds zone device coherent type.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
Reviewed-by: Alistair Poppple 
Signed-off-by: Christoph Hellwig 
---
 lib/test_hmm.c  | 23 +--
 lib/test_hmm_uapi.h |  8 
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/lib/test_hmm.c b/lib/test_hmm.c
index cfe632047839..7a27584484ce 100644
--- a/lib/test_hmm.c
+++ b/lib/test_hmm.c
@@ -87,6 +87,7 @@ struct dmirror_chunk {
 struct dmirror_device {
struct cdev cdevice;
struct hmm_devmem   *devmem;
+   unsigned intzone_device_type;
 
unsigned intdevmem_capacity;
unsigned intdevmem_count;
@@ -1026,6 +1027,15 @@ static int dmirror_snapshot(struct dmirror *dmirror,
return ret;
 }
 
+static int dmirror_get_device_type(struct dmirror *dmirror,
+   struct hmm_dmirror_cmd *cmd)
+{
+   mutex_lock(&dmirror->mutex);
+   cmd->zone_device_type = dmirror->mdevice->zone_device_type;
+   mutex_unlock(&dmirror->mutex);
+
+   return 0;
+}
 static long dmirror_fops_unlocked_ioctl(struct file *filp,
unsigned int command,
unsigned long arg)
@@ -1076,6 +1086,9 @@ static long dmirror_fops_unlocked_ioctl(struct file *filp,
ret = dmirror_snapshot(dmirror, &cmd);
break;
 
+   case HMM_DMIRROR_GET_MEM_DEV_TYPE:
+   ret = dmirror_get_device_type(dmirror, &cmd);
+   break;
default:
return -EINVAL;
}
@@ -1260,14 +1273,20 @@ static void dmirror_device_remove(struct dmirror_device 
*mdevice)
 static int __init hmm_dmirror_init(void)
 {
int ret;
-   int id;
+   int id = 0;
+   int ndevices = 0;
 
ret = alloc_chrdev_region(&dmirror_dev, 0, DMIRROR_NDEVICES,
  "HMM_DMIRROR");
if (ret)
goto err_unreg;
 
-   for (id = 0; id < DMIRROR_NDEVICES; id++) {
+   memset(dmirror_devices, 0, DMIRROR_NDEVICES * 
sizeof(dmirror_devices[0]));
+   dmirror_devices[ndevices++].zone_device_type =
+   HMM_DMIRROR_MEMORY_DEVICE_PRIVATE;
+   dmirror_devices[ndevices++].zone_device_type =
+   HMM_DMIRROR_MEMORY_DEVICE_PRIVATE;
+   for (id = 0; id < ndevices; id++) {
ret = dmirror_device_init(dmirror_devices + id, id);
if (ret)
goto err_chrdev;
diff --git a/lib/test_hmm_uapi.h b/lib/test_hmm_uapi.h
index f14dea5dcd06..17f842f1aa02 100644
--- a/lib/test_hmm_uapi.h
+++ b/lib/test_hmm_uapi.h
@@ -19,6 +19,7 @@
  * @npages: (in) number of pages to read/write
  * @cpages: (out) number of pages copied
  * @faults: (out) number of device page faults seen
+ * @zone_device_type: (out) zone device memory type
  */
 struct hmm_dmirror_cmd {
__u64   addr;
@@ -26,6 +27,7 @@ struct hmm_dmirror_cmd {
__u64   npages;
__u64   cpages;
__u64   faults;
+   __u64   zone_device_type;
 };
 
 /* Expose the address space of the calling process through hmm device file */
@@ -35,6 +37,7 @@ struct hmm_dmirror_cmd {
 #define HMM_DMIRROR_SNAPSHOT   _IOWR('H', 0x03, struct hmm_dmirror_cmd)
 #define HMM_DMIRROR_EXCLUSIVE  _IOWR('H', 0x04, struct hmm_dmirror_cmd)
 #define HMM_DMIRROR_CHECK_EXCLUSIVE_IOWR('H', 0x05, struct hmm_dmirror_cmd)
+#define HMM_DMIRROR_GET_MEM_DEV_TYPE   _IOWR('H', 0x06, struct hmm_dmirror_cmd)
 
 /*
  * Values returned in hmm_dmirror_cmd.ptr for HMM_DMIRROR_SNAPSHOT.
@@ -62,4 +65,9 @@ enum {
HMM_DMIRROR_PROT_DEV_PRIVATE_REMOTE = 0x30,
 };
 
+enum {
+   /* 0 is reserved to catch uninitialized type fields */
+   HMM_DMIRROR_MEMORY_DEVICE_PRIVATE = 1,
+};
+
 #endif /* _LIB_TEST_HMM_UAPI_H */
-- 
2.32.0



[PATCH v4 12/13] tools: add hmm gup tests for device coherent type

2022-05-31 Thread Alex Sierra
The intention is to test hmm device coherent type under different get
user pages paths. Also, test gup with FOLL_LONGTERM flag set in
device coherent pages. These pages should get migrated back to system
memory.

Signed-off-by: Alex Sierra 
Reviewed-by: Alistair Popple 
---
 tools/testing/selftests/vm/hmm-tests.c | 105 +
 1 file changed, 105 insertions(+)

diff --git a/tools/testing/selftests/vm/hmm-tests.c 
b/tools/testing/selftests/vm/hmm-tests.c
index 84ec8c4a1dc7..61a02a6a3dea 100644
--- a/tools/testing/selftests/vm/hmm-tests.c
+++ b/tools/testing/selftests/vm/hmm-tests.c
@@ -36,6 +36,7 @@
  * in the usual include/uapi/... directory.
  */
 #include "../../../../lib/test_hmm_uapi.h"
+#include "../../../../mm/gup_test.h"
 
 struct hmm_buffer {
void*ptr;
@@ -60,6 +61,8 @@ enum {
 #define NTIMES 10
 
 #define ALIGN(x, a) (((x) + (a - 1)) & (~((a) - 1)))
+/* Just the flags we need, copied from mm.h: */
+#define FOLL_WRITE 0x01/* check pte is writable */
 
 FIXTURE(hmm)
 {
@@ -1766,4 +1769,106 @@ TEST_F(hmm, exclusive_cow)
hmm_buffer_free(buffer);
 }
 
+static int gup_test_exec(int gup_fd, unsigned long addr,
+int cmd, int npages, int size)
+{
+   struct gup_test gup = {
+   .nr_pages_per_call  = npages,
+   .addr   = addr,
+   .gup_flags  = FOLL_WRITE,
+   .size   = size,
+   };
+
+   if (ioctl(gup_fd, cmd, &gup)) {
+   perror("ioctl on error\n");
+   return errno;
+   }
+
+   return 0;
+}
+
+/*
+ * Test get user device pages through gup_test. Setting PIN_LONGTERM flag.
+ * This should trigger a migration back to system memory for both, private
+ * and coherent type pages.
+ * This test makes use of gup_test module. Make sure GUP_TEST_CONFIG is added
+ * to your configuration before you run it.
+ */
+TEST_F(hmm, hmm_gup_test)
+{
+   struct hmm_buffer *buffer;
+   int gup_fd;
+   unsigned long npages;
+   unsigned long size;
+   unsigned long i;
+   int *ptr;
+   int ret;
+   unsigned char *m;
+
+   gup_fd = open("/sys/kernel/debug/gup_test", O_RDWR);
+   if (gup_fd == -1)
+   SKIP(return, "Skipping test, could not find gup_test driver");
+
+   npages = 3;
+   size = npages << self->page_shift;
+
+   buffer = malloc(sizeof(*buffer));
+   ASSERT_NE(buffer, NULL);
+
+   buffer->fd = -1;
+   buffer->size = size;
+   buffer->mirror = malloc(size);
+   ASSERT_NE(buffer->mirror, NULL);
+
+   buffer->ptr = mmap(NULL, size,
+  PROT_READ | PROT_WRITE,
+  MAP_PRIVATE | MAP_ANONYMOUS,
+  buffer->fd, 0);
+   ASSERT_NE(buffer->ptr, MAP_FAILED);
+
+   /* Initialize buffer in system memory. */
+   for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
+   ptr[i] = i;
+
+   /* Migrate memory to device. */
+   ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
+   ASSERT_EQ(ret, 0);
+   ASSERT_EQ(buffer->cpages, npages);
+   /* Check what the device read. */
+   for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
+   ASSERT_EQ(ptr[i], i);
+
+   ASSERT_EQ(gup_test_exec(gup_fd,
+   (unsigned long)buffer->ptr,
+   GUP_BASIC_TEST, 1, self->page_size), 0);
+   ASSERT_EQ(gup_test_exec(gup_fd,
+   (unsigned long)buffer->ptr + 1 * 
self->page_size,
+   GUP_FAST_BENCHMARK, 1, self->page_size), 0);
+   ASSERT_EQ(gup_test_exec(gup_fd,
+   (unsigned long)buffer->ptr + 2 * 
self->page_size,
+   PIN_LONGTERM_BENCHMARK, 1, self->page_size), 0);
+
+   /* Take snapshot to CPU pagetables */
+   ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages);
+   ASSERT_EQ(ret, 0);
+   ASSERT_EQ(buffer->cpages, npages);
+   m = buffer->mirror;
+   if (hmm_is_coherent_type(variant->device_number)) {
+   ASSERT_EQ(HMM_DMIRROR_PROT_DEV_COHERENT_LOCAL | 
HMM_DMIRROR_PROT_WRITE, m[0]);
+   ASSERT_EQ(HMM_DMIRROR_PROT_DEV_COHERENT_LOCAL | 
HMM_DMIRROR_PROT_WRITE, m[1]);
+   } else {
+   ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[0]);
+   ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[1]);
+   }
+   ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[2]);
+   /*
+* Check again the content on the pages. Make sure there's no
+* corrupted data.
+*/
+   for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
+   ASSERT_EQ(ptr[i], i);
+
+   close(gup_fd);
+   hmm_buffer_free(buffer);
+}
 TEST_HARNESS_MAIN
-- 
2.32.0



[PATCH v4 11/13] tools: update test_hmm script to support SP config

2022-05-31 Thread Alex Sierra
Add two more parameters to set spm_addr_dev0 & spm_addr_dev1
addresses. These two parameters configure the start SP
addresses for each device in test_hmm driver.
Consequently, this configures zone device type as coherent.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
Reviewed-by: Alistair Popple 
Signed-off-by: Christoph Hellwig 
---
 tools/testing/selftests/vm/test_hmm.sh | 24 +---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/vm/test_hmm.sh 
b/tools/testing/selftests/vm/test_hmm.sh
index 0647b525a625..539c9371e592 100755
--- a/tools/testing/selftests/vm/test_hmm.sh
+++ b/tools/testing/selftests/vm/test_hmm.sh
@@ -40,11 +40,26 @@ check_test_requirements()
 
 load_driver()
 {
-   modprobe $DRIVER > /dev/null 2>&1
+   if [ $# -eq 0 ]; then
+   modprobe $DRIVER > /dev/null 2>&1
+   else
+   if [ $# -eq 2 ]; then
+   modprobe $DRIVER spm_addr_dev0=$1 spm_addr_dev1=$2
+   > /dev/null 2>&1
+   else
+   echo "Missing module parameters. Make sure pass"\
+   "spm_addr_dev0 and spm_addr_dev1"
+   usage
+   fi
+   fi
if [ $? == 0 ]; then
major=$(awk "\$2==\"HMM_DMIRROR\" {print \$1}" /proc/devices)
mknod /dev/hmm_dmirror0 c $major 0
mknod /dev/hmm_dmirror1 c $major 1
+   if [ $# -eq 2 ]; then
+   mknod /dev/hmm_dmirror2 c $major 2
+   mknod /dev/hmm_dmirror3 c $major 3
+   fi
fi
 }
 
@@ -58,7 +73,7 @@ run_smoke()
 {
echo "Running smoke test. Note, this test provides basic coverage."
 
-   load_driver
+   load_driver $1 $2
$(dirname "${BASH_SOURCE[0]}")/hmm-tests
unload_driver
 }
@@ -75,6 +90,9 @@ usage()
echo "# Smoke testing"
echo "./${TEST_NAME}.sh smoke"
echo
+   echo "# Smoke testing with SPM enabled"
+   echo "./${TEST_NAME}.sh smoke  "
+   echo
exit 0
 }
 
@@ -84,7 +102,7 @@ function run_test()
usage
else
if [ "$1" = "smoke" ]; then
-   run_smoke
+   run_smoke $2 $3
else
usage
fi
-- 
2.32.0



[PATCH v4 10/13] tools: update hmm-test to support device coherent type

2022-05-31 Thread Alex Sierra
Test cases such as migrate_fault and migrate_multiple, were modified to
explicit migrate from device to sys memory without the need of page
faults, when using device coherent type.

Snapshot test case updated to read memory device type first and based
on that, get the proper returned results migrate_ping_pong test case
added to test explicit migration from device to sys memory for both
private and coherent zone types.

Helpers to migrate from device to sys memory and vicerversa
were also added.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
Reviewed-by: Alistair Popple 
Signed-off-by: Christoph Hellwig 
---
 tools/testing/selftests/vm/hmm-tests.c | 123 -
 1 file changed, 102 insertions(+), 21 deletions(-)

diff --git a/tools/testing/selftests/vm/hmm-tests.c 
b/tools/testing/selftests/vm/hmm-tests.c
index 203323967b50..84ec8c4a1dc7 100644
--- a/tools/testing/selftests/vm/hmm-tests.c
+++ b/tools/testing/selftests/vm/hmm-tests.c
@@ -44,6 +44,14 @@ struct hmm_buffer {
int fd;
uint64_tcpages;
uint64_tfaults;
+   int zone_device_type;
+};
+
+enum {
+   HMM_PRIVATE_DEVICE_ONE,
+   HMM_PRIVATE_DEVICE_TWO,
+   HMM_COHERENCE_DEVICE_ONE,
+   HMM_COHERENCE_DEVICE_TWO,
 };
 
 #define TWOMEG (1 << 21)
@@ -60,6 +68,21 @@ FIXTURE(hmm)
unsigned intpage_shift;
 };
 
+FIXTURE_VARIANT(hmm)
+{
+   int device_number;
+};
+
+FIXTURE_VARIANT_ADD(hmm, hmm_device_private)
+{
+   .device_number = HMM_PRIVATE_DEVICE_ONE,
+};
+
+FIXTURE_VARIANT_ADD(hmm, hmm_device_coherent)
+{
+   .device_number = HMM_COHERENCE_DEVICE_ONE,
+};
+
 FIXTURE(hmm2)
 {
int fd0;
@@ -68,6 +91,24 @@ FIXTURE(hmm2)
unsigned intpage_shift;
 };
 
+FIXTURE_VARIANT(hmm2)
+{
+   int device_number0;
+   int device_number1;
+};
+
+FIXTURE_VARIANT_ADD(hmm2, hmm2_device_private)
+{
+   .device_number0 = HMM_PRIVATE_DEVICE_ONE,
+   .device_number1 = HMM_PRIVATE_DEVICE_TWO,
+};
+
+FIXTURE_VARIANT_ADD(hmm2, hmm2_device_coherent)
+{
+   .device_number0 = HMM_COHERENCE_DEVICE_ONE,
+   .device_number1 = HMM_COHERENCE_DEVICE_TWO,
+};
+
 static int hmm_open(int unit)
 {
char pathname[HMM_PATH_MAX];
@@ -81,12 +122,19 @@ static int hmm_open(int unit)
return fd;
 }
 
+static bool hmm_is_coherent_type(int dev_num)
+{
+   return (dev_num >= HMM_COHERENCE_DEVICE_ONE);
+}
+
 FIXTURE_SETUP(hmm)
 {
self->page_size = sysconf(_SC_PAGE_SIZE);
self->page_shift = ffs(self->page_size) - 1;
 
-   self->fd = hmm_open(0);
+   self->fd = hmm_open(variant->device_number);
+   if (self->fd < 0 && hmm_is_coherent_type(variant->device_number))
+   SKIP(exit(0), "DEVICE_COHERENT not available");
ASSERT_GE(self->fd, 0);
 }
 
@@ -95,9 +143,11 @@ FIXTURE_SETUP(hmm2)
self->page_size = sysconf(_SC_PAGE_SIZE);
self->page_shift = ffs(self->page_size) - 1;
 
-   self->fd0 = hmm_open(0);
+   self->fd0 = hmm_open(variant->device_number0);
+   if (self->fd0 < 0 && hmm_is_coherent_type(variant->device_number0))
+   SKIP(exit(0), "DEVICE_COHERENT not available");
ASSERT_GE(self->fd0, 0);
-   self->fd1 = hmm_open(1);
+   self->fd1 = hmm_open(variant->device_number1);
ASSERT_GE(self->fd1, 0);
 }
 
@@ -144,6 +194,7 @@ static int hmm_dmirror_cmd(int fd,
}
buffer->cpages = cmd.cpages;
buffer->faults = cmd.faults;
+   buffer->zone_device_type = cmd.zone_device_type;
 
return 0;
 }
@@ -211,6 +262,20 @@ static void hmm_nanosleep(unsigned int n)
nanosleep(&t, NULL);
 }
 
+static int hmm_migrate_sys_to_dev(int fd,
+  struct hmm_buffer *buffer,
+  unsigned long npages)
+{
+   return hmm_dmirror_cmd(fd, HMM_DMIRROR_MIGRATE_TO_DEV, buffer, npages);
+}
+
+static int hmm_migrate_dev_to_sys(int fd,
+  struct hmm_buffer *buffer,
+  unsigned long npages)
+{
+   return hmm_dmirror_cmd(fd, HMM_DMIRROR_MIGRATE_TO_SYS, buffer, npages);
+}
+
 /*
  * Simple NULL test of device open/close.
  */
@@ -875,7 +940,7 @@ TEST_F(hmm, migrate)
ptr[i] = i;
 
/* Migrate memory to device. */
-   ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_MIGRATE, buffer, npages);
+   ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
ASSERT_EQ(ret, 0);
ASSERT_EQ(buffer->cpages, npages);
 
@@ -923,7 +988,7 @@ TEST_F(hmm, migrate_fault)
ptr[i] = i;
 
/* Migrate memory to device. */
-   ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_MIGRATE, buffer, npages);
+   ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
ASSERT_EQ(ret, 0);
ASSERT_EQ(buffer->cpages, npages);
 
@@ -936,7 +1001,7 @@ TEST_F(hmm, migrate_fault)
ASSERT_EQ(ptr[i], i);

[PATCH v4 08/13] lib: test_hmm add module param for zone device type

2022-05-31 Thread Alex Sierra
In order to configure device coherent in test_hmm, two module parameters
should be passed, which correspond to the SP start address of each
device (2) spm_addr_dev0 & spm_addr_dev1. If no parameters are passed,
private device type is configured.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
Reviewed-by: Alistair Poppple 
Signed-off-by: Christoph Hellwig 
---
 lib/test_hmm.c  | 73 -
 lib/test_hmm_uapi.h |  1 +
 2 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/lib/test_hmm.c b/lib/test_hmm.c
index 7a27584484ce..15747f70c5bc 100644
--- a/lib/test_hmm.c
+++ b/lib/test_hmm.c
@@ -37,6 +37,16 @@
 #define DEVMEM_CHUNK_SIZE  (256 * 1024 * 1024U)
 #define DEVMEM_CHUNKS_RESERVE  16
 
+static unsigned long spm_addr_dev0;
+module_param(spm_addr_dev0, long, 0644);
+MODULE_PARM_DESC(spm_addr_dev0,
+   "Specify start address for SPM (special purpose memory) used 
for device 0. By setting this Coherent device type will be used. Make sure 
spm_addr_dev1 is set too. Minimum SPM size should be DEVMEM_CHUNK_SIZE.");
+
+static unsigned long spm_addr_dev1;
+module_param(spm_addr_dev1, long, 0644);
+MODULE_PARM_DESC(spm_addr_dev1,
+   "Specify start address for SPM (special purpose memory) used 
for device 1. By setting this Coherent device type will be used. Make sure 
spm_addr_dev0 is set too. Minimum SPM size should be DEVMEM_CHUNK_SIZE.");
+
 static const struct dev_pagemap_ops dmirror_devmem_ops;
 static const struct mmu_interval_notifier_ops dmirror_min_ops;
 static dev_t dmirror_dev;
@@ -455,28 +465,44 @@ static int dmirror_write(struct dmirror *dmirror, struct 
hmm_dmirror_cmd *cmd)
return ret;
 }
 
-static bool dmirror_allocate_chunk(struct dmirror_device *mdevice,
+static int dmirror_allocate_chunk(struct dmirror_device *mdevice,
   struct page **ppage)
 {
struct dmirror_chunk *devmem;
-   struct resource *res;
+   struct resource *res = NULL;
unsigned long pfn;
unsigned long pfn_first;
unsigned long pfn_last;
void *ptr;
+   int ret = -ENOMEM;
 
devmem = kzalloc(sizeof(*devmem), GFP_KERNEL);
if (!devmem)
-   return false;
+   return ret;
 
-   res = request_free_mem_region(&iomem_resource, DEVMEM_CHUNK_SIZE,
- "hmm_dmirror");
-   if (IS_ERR(res))
+   switch (mdevice->zone_device_type) {
+   case HMM_DMIRROR_MEMORY_DEVICE_PRIVATE:
+   res = request_free_mem_region(&iomem_resource, 
DEVMEM_CHUNK_SIZE,
+ "hmm_dmirror");
+   if (IS_ERR_OR_NULL(res))
+   goto err_devmem;
+   devmem->pagemap.range.start = res->start;
+   devmem->pagemap.range.end = res->end;
+   devmem->pagemap.type = MEMORY_DEVICE_PRIVATE;
+   break;
+   case HMM_DMIRROR_MEMORY_DEVICE_COHERENT:
+   devmem->pagemap.range.start = (MINOR(mdevice->cdevice.dev) - 2) 
?
+   spm_addr_dev0 :
+   spm_addr_dev1;
+   devmem->pagemap.range.end = devmem->pagemap.range.start +
+   DEVMEM_CHUNK_SIZE - 1;
+   devmem->pagemap.type = MEMORY_DEVICE_COHERENT;
+   break;
+   default:
+   ret = -EINVAL;
goto err_devmem;
+   }
 
-   devmem->pagemap.type = MEMORY_DEVICE_PRIVATE;
-   devmem->pagemap.range.start = res->start;
-   devmem->pagemap.range.end = res->end;
devmem->pagemap.nr_range = 1;
devmem->pagemap.ops = &dmirror_devmem_ops;
devmem->pagemap.owner = mdevice;
@@ -497,10 +523,14 @@ static bool dmirror_allocate_chunk(struct dmirror_device 
*mdevice,
mdevice->devmem_capacity = new_capacity;
mdevice->devmem_chunks = new_chunks;
}
-
ptr = memremap_pages(&devmem->pagemap, numa_node_id());
-   if (IS_ERR(ptr))
+   if (IS_ERR_OR_NULL(ptr)) {
+   if (ptr)
+   ret = PTR_ERR(ptr);
+   else
+   ret = -EFAULT;
goto err_release;
+   }
 
devmem->mdevice = mdevice;
pfn_first = devmem->pagemap.range.start >> PAGE_SHIFT;
@@ -529,15 +559,17 @@ static bool dmirror_allocate_chunk(struct dmirror_device 
*mdevice,
}
spin_unlock(&mdevice->lock);
 
-   return true;
+   return 0;
 
 err_release:
mutex_unlock(&mdevice->devmem_lock);
-   release_mem_region(devmem->pagemap.range.start, 
range_len(&devmem->pagemap.range));
+   if (res && devmem->pagemap.type == MEMORY_DEVICE_PRIVATE)
+   release_mem_region(devmem->pagemap.range.start,
+  range_len(&devmem->pagemap.range));
 

[PATCH v4 13/13] tools: add selftests to hmm for COW in device memory

2022-05-31 Thread Alex Sierra
The objective is to test device migration mechanism in pages marked
as COW, for private and coherent device type. In case of writing to
COW private page(s), a page fault will migrate pages back to system
memory first. Then, these pages will be duplicated. In case of COW
device coherent type, pages are duplicated directly from device
memory.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
---
 tools/testing/selftests/vm/hmm-tests.c | 80 ++
 1 file changed, 80 insertions(+)

diff --git a/tools/testing/selftests/vm/hmm-tests.c 
b/tools/testing/selftests/vm/hmm-tests.c
index 61a02a6a3dea..76570030ba5b 100644
--- a/tools/testing/selftests/vm/hmm-tests.c
+++ b/tools/testing/selftests/vm/hmm-tests.c
@@ -1871,4 +1871,84 @@ TEST_F(hmm, hmm_gup_test)
close(gup_fd);
hmm_buffer_free(buffer);
 }
+
+/*
+ * Test copy-on-write in device pages.
+ * In case of writing to COW private page(s), a page fault will migrate pages
+ * back to system memory first. Then, these pages will be duplicated. In case
+ * of COW device coherent type, pages are duplicated directly from device
+ * memory.
+ */
+TEST_F(hmm, hmm_cow_in_device)
+{
+   struct hmm_buffer *buffer;
+   unsigned long npages;
+   unsigned long size;
+   unsigned long i;
+   int *ptr;
+   int ret;
+   unsigned char *m;
+   pid_t pid;
+   int status;
+
+   npages = 4;
+   size = npages << self->page_shift;
+
+   buffer = malloc(sizeof(*buffer));
+   ASSERT_NE(buffer, NULL);
+
+   buffer->fd = -1;
+   buffer->size = size;
+   buffer->mirror = malloc(size);
+   ASSERT_NE(buffer->mirror, NULL);
+
+   buffer->ptr = mmap(NULL, size,
+  PROT_READ | PROT_WRITE,
+  MAP_PRIVATE | MAP_ANONYMOUS,
+  buffer->fd, 0);
+   ASSERT_NE(buffer->ptr, MAP_FAILED);
+
+   /* Initialize buffer in system memory. */
+   for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
+   ptr[i] = i;
+
+   /* Migrate memory to device. */
+
+   ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
+   ASSERT_EQ(ret, 0);
+   ASSERT_EQ(buffer->cpages, npages);
+
+   pid = fork();
+   if (pid == -1)
+   ASSERT_EQ(pid, 0);
+   if (!pid) {
+   /* Child process waitd for SIGTERM from the parent. */
+   while (1) {
+   }
+   perror("Should not reach this\n");
+   exit(0);
+   }
+   /* Parent process writes to COW pages(s) and gets a
+* new copy in system. In case of device private pages,
+* this write causes a migration to system mem first.
+*/
+   for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
+   ptr[i] = i;
+
+   /* Terminate child and wait */
+   EXPECT_EQ(0, kill(pid, SIGTERM));
+   EXPECT_EQ(pid, waitpid(pid, &status, 0));
+   EXPECT_NE(0, WIFSIGNALED(status));
+   EXPECT_EQ(SIGTERM, WTERMSIG(status));
+
+   /* Take snapshot to CPU pagetables */
+   ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages);
+   ASSERT_EQ(ret, 0);
+   ASSERT_EQ(buffer->cpages, npages);
+   m = buffer->mirror;
+   for (i = 0; i < npages; i++)
+   ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[i]);
+
+   hmm_buffer_free(buffer);
+}
 TEST_HARNESS_MAIN
-- 
2.32.0



[PATCH v4 09/13] lib: add support for device coherent type in test_hmm

2022-05-31 Thread Alex Sierra
Device Coherent type uses device memory that is coherently accesible by
the CPU. This could be shown as SP (special purpose) memory range
at the BIOS-e820 memory enumeration. If no SP memory is supported in
system, this could be faked by setting CONFIG_EFI_FAKE_MEMMAP.

Currently, test_hmm only supports two different SP ranges of at least
256MB size. This could be specified in the kernel parameter variable
efi_fake_mem. Ex. Two SP ranges of 1GB starting at 0x1 &
0x14000 physical address. Ex.
efi_fake_mem=1G@0x1:0x4,1G@0x14000:0x4

Private and coherent device mirror instances can be created in the same
probed. This is done by passing the module parameters spm_addr_dev0 &
spm_addr_dev1. In this case, it will create four instances of
device_mirror. The first two correspond to private device type, the
last two to coherent type. Then, they can be easily accessed from user
space through /dev/hmm_mirror. Usually num_device 0 and 1
are for private, and 2 and 3 for coherent types. If no module
parameters are passed, two instances of private type device_mirror will
be created only.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
Reviewed-by: Alistair Poppple 
---
 lib/test_hmm.c  | 253 +---
 lib/test_hmm_uapi.h |  15 ++-
 2 files changed, 202 insertions(+), 66 deletions(-)

diff --git a/lib/test_hmm.c b/lib/test_hmm.c
index 15747f70c5bc..361a026c5d21 100644
--- a/lib/test_hmm.c
+++ b/lib/test_hmm.c
@@ -32,11 +32,22 @@
 
 #include "test_hmm_uapi.h"
 
-#define DMIRROR_NDEVICES   2
+#define DMIRROR_NDEVICES   4
 #define DMIRROR_RANGE_FAULT_TIMEOUT1000
 #define DEVMEM_CHUNK_SIZE  (256 * 1024 * 1024U)
 #define DEVMEM_CHUNKS_RESERVE  16
 
+/*
+ * For device_private pages, dpage is just a dummy struct page
+ * representing a piece of device memory. dmirror_devmem_alloc_page
+ * allocates a real system memory page as backing storage to fake a
+ * real device. zone_device_data points to that backing page. But
+ * for device_coherent memory, the struct page represents real
+ * physical CPU-accessible memory that we can use directly.
+ */
+#define BACKING_PAGE(page) (is_device_private_page((page)) ? \
+  (page)->zone_device_data : (page))
+
 static unsigned long spm_addr_dev0;
 module_param(spm_addr_dev0, long, 0644);
 MODULE_PARM_DESC(spm_addr_dev0,
@@ -125,6 +136,21 @@ static int dmirror_bounce_init(struct dmirror_bounce 
*bounce,
return 0;
 }
 
+static bool dmirror_is_private_zone(struct dmirror_device *mdevice)
+{
+   return (mdevice->zone_device_type ==
+   HMM_DMIRROR_MEMORY_DEVICE_PRIVATE) ? true : false;
+}
+
+static enum migrate_vma_direction
+dmirror_select_device(struct dmirror *dmirror)
+{
+   return (dmirror->mdevice->zone_device_type ==
+   HMM_DMIRROR_MEMORY_DEVICE_PRIVATE) ?
+   MIGRATE_VMA_SELECT_DEVICE_PRIVATE :
+   MIGRATE_VMA_SELECT_DEVICE_COHERENT;
+}
+
 static void dmirror_bounce_fini(struct dmirror_bounce *bounce)
 {
vfree(bounce->ptr);
@@ -575,16 +601,19 @@ static int dmirror_allocate_chunk(struct dmirror_device 
*mdevice,
 static struct page *dmirror_devmem_alloc_page(struct dmirror_device *mdevice)
 {
struct page *dpage = NULL;
-   struct page *rpage;
+   struct page *rpage = NULL;
 
/*
-* This is a fake device so we alloc real system memory to store
-* our device memory.
+* For ZONE_DEVICE private type, this is a fake device so we allocate
+* real system memory to store our device memory.
+* For ZONE_DEVICE coherent type we use the actual dpage to store the
+* data and ignore rpage.
 */
-   rpage = alloc_page(GFP_HIGHUSER);
-   if (!rpage)
-   return NULL;
-
+   if (dmirror_is_private_zone(mdevice)) {
+   rpage = alloc_page(GFP_HIGHUSER);
+   if (!rpage)
+   return NULL;
+   }
spin_lock(&mdevice->lock);
 
if (mdevice->free_pages) {
@@ -603,7 +632,8 @@ static struct page *dmirror_devmem_alloc_page(struct 
dmirror_device *mdevice)
return dpage;
 
 error:
-   __free_page(rpage);
+   if (rpage)
+   __free_page(rpage);
return NULL;
 }
 
@@ -629,12 +659,16 @@ static void dmirror_migrate_alloc_and_copy(struct 
migrate_vma *args,
 * unallocated pte_none() or read-only zero page.
 */
spage = migrate_pfn_to_page(*src);
+   if (WARN(spage && is_zone_device_page(spage),
+"page already in device spage pfn: 0x%lx\n",
+page_to_pfn(spage)))
+   continue;
 
dpage = dmirror_devmem_alloc_page(mdevice);
if (!dpage)
continue;
 
-   rpage = dpage->zone_device_data;
+   rpage = BACKING_PAGE(dpage);
 

[Bug 205089] amdgpu : drm:amdgpu_cs_ioctl : Failed to initialize parser -125

2022-05-31 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=205089

--- Comment #45 from Alex Deucher (alexdeuc...@gmail.com) ---
The "Failed to initialize parser -125!" error message is a generic symptom of a
GPU hang and reset.  The actual cause of the GPU hang is very likely different
for everyone.  The issue is mostly likely in mesa (which handles the user mode
side of graphics and video acceleration).  An improperly set up command buffer
from the user mode driver could cause a GPU hang.  In that case the kernel is
just the messenger.  I would suggest trying a newer or older mesa release to
see if you can narrow down the issue.  If there is a specific application that
causes the issue consistently, I would suggest opening a mesa bug report
(https://gitlab.freedesktop.org/groups/mesa/-/issues?sort=updated_desc&state=opened).

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.

Re: mainline build failure due to f1e4c916f97f ("drm/edid: add EDID block count and size helpers")

2022-05-31 Thread Linus Torvalds
On Tue, May 31, 2022 at 1:04 AM Arnd Bergmann  wrote:
>
> As an experiment: what kind of results would we get when looking
> for packed structures and unions that contain any of these:

Yeah, any atomics or locks should always be aligned, and won't even
work (or might be *very* slow) on multiple architectures. Even x86 -
which does very well on unaligned data - reacts badly to sufficiently
unaligned atomics (ie cacheline crossing).

I don't think we have that. Not only because it would already cause
breakage, but simply because the kinds of structures that people pack
aren't generally the kind that contain these kinds of things.

That said, you might have a struct that is packed, but that
intentionally aligns parts of itself, so it *could* be valid.

But it would probably not be a bad idea to check that packed
structures/unions don't have atomic types or locks in them. I _think_
we're all good, but who knows..

Linus


Re: [PATCH] drm/edid: ignore the CEA modes not defined in CEA-861-D

2022-05-31 Thread Ville Syrjälä
On Tue, May 31, 2022 at 06:34:21PM +0800, William Tseng wrote:
> This is a workaround for HDMI 1.4 sink which has a CEA mode with higher vic
> than what is defined in CEA-861-D.
> 
> As an example, a HDMI 1.4 sink has the video format 2560x1080p to be
> displayed and the video format is indicated by both SVD (with vic 90 and
> pictuure aspect ratio 64:27) and DTD.  When connecting to such sink,
> source can't output the video format in SVD because an error is returned by
> drm_hdmi_avi_infoframe_from_display_mode(), which can't fill the infoframe
> with pictuure aspect ratio 64:27 and the vic, which is originally 90 and is
> changed to 0 by drm_mode_cea_vic().

Hmm. I think either we need to change the logic in
drm_hdmi_avi_infoframe_from_display_mode() somehow to accept this
or we need to strip the aspect ratio from such modes when we probe
them.

The first option might be nicer, and something like this might even work:

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 929fc0e46751..3d5c76acf42a 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6082,7 +6082,8 @@ static u8 drm_mode_hdmi_vic(const struct drm_connector 
*connector,
 }
 
 static u8 drm_mode_cea_vic(const struct drm_connector *connector,
-  const struct drm_display_mode *mode)
+  const struct drm_display_mode *mode,
+  bool is_hdmi2_sink)
 {
u8 vic;
 
@@ -6102,7 +6103,7 @@ static u8 drm_mode_cea_vic(const struct drm_connector 
*connector,
 * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
 * have to make sure we dont break HDMI 1.4 sinks.
 */
-   if (!is_hdmi2_sink(connector) && vic > 64)
+   if (!is_hdmi2_sink && vic > 64)
return 0;
 
return vic;
@@ -6133,7 +6134,7 @@ drm_hdmi_avi_infoframe_from_display_mode(struct 
hdmi_avi_infoframe *frame,
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
frame->pixel_repeat = 1;
 
-   vic = drm_mode_cea_vic(connector, mode);
+   vic = drm_mode_cea_vic(connector, mode, true);
hdmi_vic = drm_mode_hdmi_vic(connector, mode);
 
frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
@@ -6177,7 +6178,7 @@ drm_hdmi_avi_infoframe_from_display_mode(struct 
hdmi_avi_infoframe *frame,
picture_aspect = HDMI_PICTURE_ASPECT_NONE;
}
 
-   frame->video_code = vic;
+   frame->video_code = drm_mode_cea_vic(connector, mode, 
is_hdmi2_sink(connector));
frame->picture_aspect = picture_aspect;
frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
frame->scan_mode = HDMI_SCAN_MODE_UNDERSCAN;

But I don't quite remember off hand how the CEA VIC vs. HDMI VIC
decision plays into this, so there might be some issues with that
approach.

-- 
Ville Syrjälä
Intel


Re: [RFC V3 1/2] drm/vrr: Attach vrr_enabled property to the drm crtc

2022-05-31 Thread Navare, Manasi
On Tue, May 17, 2022 at 12:56:35PM +0530, Bhanuprakash Modem wrote:
> Modern display hardware is capable of supporting variable refresh rates.
> This patch introduces helpers to attach and set "vrr_enabled" property
> on the crtc to allow userspace to query VRR enabled status on that crtc.
> 
> Atomic drivers should attach this property to crtcs those are capable of
> driving variable refresh rates using
> drm_mode_crtc_attach_vrr_enabled_property().

We are not attaching the prop anymore, please remove this from the
commit message.

> 
> The value should be updated based on driver and hardware capability
> by using drm_mode_crtc_set_vrr_enabled_property().
> 
> V2: Use property flag as atomic
> V3: Drop helper to attach vrr_enabled prop, since it is already
> attached (Manasi)
> 
> Cc: Ville Syrjälä 
> Cc: Nicholas Kazlauskas 
> Cc: Manasi Navare 
> Cc: Harry Wentland 
> Signed-off-by: Bhanuprakash Modem 
> ---
>  drivers/gpu/drm/drm_crtc.c| 26 ++
>  drivers/gpu/drm/drm_mode_config.c |  2 +-
>  include/drm/drm_crtc.h|  3 +++
>  3 files changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 26a77a735905..8bb8b4bf4199 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -239,6 +239,9 @@ struct dma_fence *drm_crtc_create_fence(struct drm_crtc 
> *crtc)
>   *   Driver's default scaling filter
>   *   Nearest Neighbor:
>   *   Nearest Neighbor scaling filter
> + * VRR_ENABLED:
> + *   Atomic property for setting the VRR state of the CRTC.
> + *   To enable the VRR on CRTC, user-space must set this property to 1.

This prop was primarily a userspace Write only and driver read only
property which would be used only by the userspace to request VRR on
that CRTC,

Are we now modifying this to be used as a bidirectional property to also
indicate the status of VRR on that CRTC which will be updated by the
driver?

We need to add this accordingly and update the DRM documentation and
also get acks from other vendors since AMD and other folks mght be using
this as a write only prop.

Manasi

>   */
>  
>  __printf(6, 0)
> @@ -883,3 +886,26 @@ int drm_crtc_create_scaling_filter_property(struct 
> drm_crtc *crtc,
>   return 0;
>  }
>  EXPORT_SYMBOL(drm_crtc_create_scaling_filter_property);
> +
> +/**
> + * drm_mode_crtc_set_vrr_enabled_property - sets the vrr enabled property for
> + * a crtc.
> + * @crtc: drm CRTC
> + * @vrr_enabled: True to enable the VRR on CRTC
> + *
> + * Should be used by atomic drivers to update the VRR enabled status on a 
> CRTC
> + */
> +void drm_mode_crtc_set_vrr_enabled_property(struct drm_crtc *crtc,
> + bool vrr_enabled)
> +{
> + struct drm_device *dev = crtc->dev;
> + struct drm_mode_config *config = &dev->mode_config;
> +
> + if (!config->prop_vrr_enabled)
> + return;
> +
> + drm_object_property_set_value(&crtc->base,
> +   config->prop_vrr_enabled,
> +   vrr_enabled);
> +}
> +EXPORT_SYMBOL(drm_mode_crtc_set_vrr_enabled_property);
> diff --git a/drivers/gpu/drm/drm_mode_config.c 
> b/drivers/gpu/drm/drm_mode_config.c
> index 37b4b9f0e468..b7cde73d5586 100644
> --- a/drivers/gpu/drm/drm_mode_config.c
> +++ b/drivers/gpu/drm/drm_mode_config.c
> @@ -323,7 +323,7 @@ static int drm_mode_create_standard_properties(struct 
> drm_device *dev)
>   return -ENOMEM;
>   dev->mode_config.prop_mode_id = prop;
>  
> - prop = drm_property_create_bool(dev, 0,
> + prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
>   "VRR_ENABLED");
>   if (!prop)
>   return -ENOMEM;
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index a70baea0636c..906787398f40 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -1333,4 +1333,7 @@ static inline struct drm_crtc *drm_crtc_find(struct 
> drm_device *dev,
>  int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc,
>   unsigned int supported_filters);
>  
> +void drm_mode_crtc_set_vrr_enabled_property(struct drm_crtc *crtc,
> + bool vrr_enabled);
> +
>  #endif /* __DRM_CRTC_H__ */
> -- 
> 2.35.1
> 


Re: [RFC V3 2/2] drm/i915/vrr: Set drm crtc vrr_enabled property

2022-05-31 Thread Navare, Manasi
On Tue, May 17, 2022 at 12:56:36PM +0530, Bhanuprakash Modem wrote:
> This function sets the vrr_enabled property for crtc based
> on the platform support and the request from userspace.
> 
> V2: Check for platform support before updating the prop.
> V3: Don't attach vrr_enabled prop, as it is alreay attached.
> 
> Cc: Ville Syrjälä 
> Cc: Manasi Navare 
> Signed-off-by: Bhanuprakash Modem 
> ---
>  drivers/gpu/drm/i915/display/intel_vrr.c | 8 
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
> b/drivers/gpu/drm/i915/display/intel_vrr.c
> index 396f2f994fa0..7263b35550de 100644
> --- a/drivers/gpu/drm/i915/display/intel_vrr.c
> +++ b/drivers/gpu/drm/i915/display/intel_vrr.c
> @@ -160,6 +160,10 @@ void intel_vrr_enable(struct intel_encoder *encoder,
>   enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
>   u32 trans_vrr_ctl;
>  
> + if (HAS_VRR(dev_priv))
> + drm_mode_crtc_set_vrr_enabled_property(crtc_state->uapi.crtc,
> +crtc_state->vrr.enable);

But here if userspace has accidently set the CRTC vrr enabled prop to
true without cheking VRR capabile prop, this will be true and here the
driver will still not
reset it. If that is the purpose of adding this then we should infact
set this to false if !HAS_VRR

Manasi

> +
>   if (!crtc_state->vrr.enable)
>   return;
>  
> @@ -211,6 +215,10 @@ void intel_vrr_disable(const struct intel_crtc_state 
> *old_crtc_state)
>   struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>   enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
>  
> + if (HAS_VRR(dev_priv))
> + 
> drm_mode_crtc_set_vrr_enabled_property(old_crtc_state->uapi.crtc,
> +false);
> +
>   if (!old_crtc_state->vrr.enable)
>   return;
>  
> -- 
> 2.35.1
> 


Re: [PATCH v4 07/13] lib: test_hmm add ioctl to get zone device type

2022-05-31 Thread Andrew Morton
On Tue, 31 May 2022 10:56:23 -0500 Alex Sierra  wrote:

> new ioctl cmd added to query zone device type. This will be
> used once the test_hmm adds zone device coherent type.
> 
> @@ -1026,6 +1027,15 @@ static int dmirror_snapshot(struct dmirror *dmirror,
>   return ret;
>  }
>  
> +static int dmirror_get_device_type(struct dmirror *dmirror,
> + struct hmm_dmirror_cmd *cmd)
> +{
> + mutex_lock(&dmirror->mutex);
> + cmd->zone_device_type = dmirror->mdevice->zone_device_type;
> + mutex_unlock(&dmirror->mutex);

What does the locking here do?

Presumably cmd->zone_device_type can become out of date the instant the
mutex is released, so what was the point in taking the mutex?

And does it make sense to return potentially out-of-date info to
userspace?  Perhaps this interface simply shouldn't exist?


Re: How should "max bpc" KMS property work?

2022-05-31 Thread Ville Syrjälä
On Wed, May 25, 2022 at 01:36:47PM +0300, Pekka Paalanen wrote:
> On Wed, 25 May 2022 09:23:51 +
> Simon Ser  wrote:
> 
> > On Wednesday, May 25th, 2022 at 10:35, Michel Dänzer 
> >  wrote:
> > 
> > > > Mind that "max bpc" is always in auto. It's only an upper limit, with
> > > > the assumption that the driver can choose less.  
> > >
> > > It seems to me like the "max bpc" property is just kind of bad API,
> > > and trying to tweak it to cater to more use cases as we discover them
> > > will take us down a rabbit hole. It seems better to replace it with
> > > new properties which allow user space to determine the current
> > > effective bpc and to explicitly control it.  
> > 
> > +1, this sounds much more robust, and allows better control by user-space.
> > User-space needs to have fallback logic for other state as well anyways.
> > If the combinatorial explosion is too much, we should think about optimizing
> > the KMS implementation, or improve the uAPI.
> 
> +1 as well, with some recommendations added and the running off to the
> sunset:
> 
> Use two separate KMS properties for reporting current vs.
> programming desired. The KMS property reporting the current value
> must be read-only (immutable). This preserves the difference between
> what userspace wanted and what it got, making it possible to read
> back both without confusing them. It also allows preserving driver behaviour

I don't see much real point in a property to report the current bpc.
That can't be used to do anything atomically. So I suppose plymouth
would be the only user.

So IMO if someone really need explicit control over this then we 
should just expose properties to set things explicitly. So we'd
need at least props for the actual bpc and some kind of color 
encoding property (RGB/YCbCr 4:4:4/4:2:2:/4:2:0, etc.). And someone
would really need to figure out how DSC would interact with those.

For just the plymouth case I guess the easiest thing would be to
just clamp "max bpc" to the current value. The problem with that
is that we'd potentially break existing userspace. Eg. I don't think
the modesetting ddx or perhaps even most of the wayland compositors
set "max bpc" at all. So we'd need to roll out a bunch of userspace
updates first. And the "current bpc" prop idea would also have this
same problem since plymouth would just clamp "max bpc" based on the
current bpc before the real userspace starts.

-- 
Ville Syrjälä
Intel


Re: [PATCH] drm/msm/dpu: Fix pointer dereferenced before checking

2022-05-31 Thread Abhinav Kumar




On 5/29/2022 7:19 PM, Haowen Bai wrote:

The phys_enc->wb_idx is dereferencing before null checking, so move
it after checking.

Signed-off-by: Haowen Bai 


Fixes: d7d0e73f7de33 ("drm/msm/dpu: introduce the dpu_encoder_phys_* for 
writeback")


Reviewed-by: Abhinav Kumar 


---
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index 4829d1ce0cf8..59da348ff339 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -574,11 +574,11 @@ static void dpu_encoder_phys_wb_disable(struct 
dpu_encoder_phys *phys_enc)
   */
  static void dpu_encoder_phys_wb_destroy(struct dpu_encoder_phys *phys_enc)
  {
-   DPU_DEBUG("[wb:%d]\n", phys_enc->wb_idx - WB_0);
-
if (!phys_enc)
return;
  
+	DPU_DEBUG("[wb:%d]\n", phys_enc->wb_idx - WB_0);

+
kfree(phys_enc);
  }
  


Re: [PATCH v3] dma-buf: Add a capabilities directory

2022-05-31 Thread Jason Ekstrand
On Mon, 2022-05-30 at 10:26 +0200, Greg KH wrote:
> On Mon, May 30, 2022 at 08:15:04AM +, Simon Ser wrote:
> > On Monday, May 30th, 2022 at 09:20, Greg KH
> >  wrote:
> > 
> > > > > +static struct attribute *dma_buf_caps_attrs[] = {
> > > > > +   &dma_buf_sync_file_import_export_attr.attr,
> > > > > +   NULL,
> > > > > +};
> > > > > +
> > > > > +static const struct attribute_group dma_buf_caps_attr_group
> > > > > = {
> > > > > +   .attrs = dma_buf_caps_attrs,
> > > > > +};
> > > > 
> > > > Didn't we had macros for those? I think I have seen something
> > > > for that.
> > > 
> > > Yes, please use ATTRIBUTE_GROUPS()
> > 
> > This doesn't allow the user to set a group name, and creates an
> > unused
> > "_groups" variable, causing warnings.
> 
> Then set a group name.
> 
> But you really want to almost always be using lists of groups, which
> is
> why that macro works that way.

I think I see the confusion here.  The ATTRIBUTE_GROUPS() macro is
intended for device drivers and to be used with add_device().  However,
this is dma-buf so there is no device and no add_device() call to hook.
Unless there are other magic macros to use in this case, I think we're
stuck doing it manually.

--Jason


> > 
> > > > > +
> > > > > +static struct kobject *dma_buf_caps_kobj;
> > > > > +
> > > > > +int dma_buf_init_sysfs_capabilities(struct kset *kset)
> > > > > +{
> > > > > +   int ret;
> > > > > +
> > > > > +   dma_buf_caps_kobj = kobject_create_and_add("caps",
> > > > > &kset->kobj);
> > > > > +   if (!dma_buf_caps_kobj)
> > > > > +   return -ENOMEM;
> > > > > +
> > > > > +   ret = sysfs_create_group(dma_buf_caps_kobj,
> > > > > &dma_buf_caps_attr_group);
> > > 
> > > Why do we have "raw" kobjects here?
> > > 
> > > A group can have a name, which puts it in the subdirectory of the
> > > object
> > > it is attached to.  Please do that and do not create a new
> > > kobject.
> > 
> > I see, I'll switch to sysfs_create_group with a group name in the
> > next version.
> 
> No, do not do that, add it to the list of groups for the original
> kobject.
> 
> thanks,
> 
> greg k-h



[RESEND 05/14] dt-bindings: backlight: Add Mediatek MT6370 backlight binding

2022-05-31 Thread ChiaEn Wu
From: ChiYuan Huang 

Add mt6370 backlight binding documentation.

Signed-off-by: ChiYuan Huang 
---
 .../backlight/mediatek,mt6370-backlight.yaml  | 110 ++
 1 file changed, 110 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/leds/backlight/mediatek,mt6370-backlight.yaml

diff --git 
a/Documentation/devicetree/bindings/leds/backlight/mediatek,mt6370-backlight.yaml
 
b/Documentation/devicetree/bindings/leds/backlight/mediatek,mt6370-backlight.yaml
new file mode 100644
index ..81d72ed44be4
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/leds/backlight/mediatek,mt6370-backlight.yaml
@@ -0,0 +1,110 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: 
http://devicetree.org/schemas/leds/backlight/mediatek,mt6370-backlight.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT6370 Backlight
+
+maintainers:
+  - ChiaEn Wu 
+
+description: |
+  MT6370 is a highly-integrated smart power management IC, which includes a
+  single cell Li-Ion/Li-Polymer switching battery charger, a USB Type-C &
+  Power Delivery (PD) controller, dual flash LED current sources, a RGB LED
+  driver, a backlight WLED driver, a display bias driver and a general LDO for
+  portable devices.
+
+  For the LCD backlight, it can provide 4 channel WLED driving capability.
+  Each channel driving current is up to 30mA
+
+allOf:
+  - $ref: common.yaml#
+
+properties:
+  compatible:
+const: mediatek,mt6370-backlight
+
+  default-brightness:
+minimum: 0
+maximum: 2048
+
+  max-brightness:
+minimum: 0
+maximum: 2048
+
+  enable-gpios:
+description: External backlight 'enable' pin
+maxItems: 1
+
+  mediatek,bled-pwm-enable:
+description: |
+  Enable external PWM input for backlight dimming
+type: boolean
+
+  mediatek,bled-pwm-hys-enable:
+description: |
+  Enable the backlight input-hysteresis for PWM mode
+type: boolean
+
+  mediatek,bled-pwm-hys-sel:
+$ref: /schemas/types.yaml#/definitions/uint8
+enum: [0, 1, 2, 3]
+description: |
+  Backlight PWM hysteresis input level selection.
+  value mapping:
+- 0: 1bit
+- 1: 2bit
+- 2: 4bit
+- 3: 6bit
+
+  mediatek,bled-ovp-shutdown:
+description: |
+  Enable the backlight shutdown when OVP level triggered
+type: boolean
+
+  mediatek,bled-ovp-level-sel:
+$ref: /schemas/types.yaml#/definitions/uint8
+enum: [0, 1, 2, 3]
+description: |
+  Backlight OVP level selection.
+  value mapping:
+- 0: 17V
+- 1: 21V
+- 2: 25V
+- 3: 29V
+
+  mediatek,bled-ocp-shutdown:
+description: |
+  Enable the backlight shutdown when OCP level triggerred.
+type: boolean
+
+  mediatek,bled-ocp-level-sel:
+$ref: /schemas/types.yaml#/definitions/uint8
+enum: [0, 1, 2, 3]
+description: |
+  Backlight OC level selection.
+  value mapping:
+- 0: 900mA
+- 1: 1200mA
+- 2: 1500mA
+- 3: 1800mA
+
+  mediatek,bled-channel-use:
+$ref: /schemas/types.yaml#/definitions/uint8
+description: |
+  Backlight LED channel to be used.
+  Each bit mapping to:
+- 0: CH4
+- 1: CH3
+- 2: CH2
+- 3: CH1
+minimum: 1
+maximum: 15
+
+required:
+  - compatible
+  - mediatek,bled-channel-use
+
+additionalProperties: false
-- 
2.25.1



[RESEND 00/14] Add Mediatek MT6370 PMIC support

2022-05-31 Thread ChiaEn Wu
From: ChiaEn Wu 

Sorry, for the patch dependency, we resend this patch series and we're
sorry for any inconvenience that we may have caused. This patch series add
Mediatek MT6370 PMIC support. The MT6370 is a highly-integrated smart
power management IC, which includes a single cell Li-Ion/Li-Polymer
switching battery charger, a USB Type-C & Power Delivery (PD)
controller, dual Flash LED current sources, a RGB LED driver, a
backlight WLED driver, a display bias driver and a general LDO for
portable devices.

Alice Chen (3):
  dt-bindings: leds: Add Mediatek MT6370 flashlight binding
  leds: mt6370: Add Mediatek MT6370 Indicator support
  leds: flashlight: mt6370: Add Mediatek MT6370 flashlight support

ChiYuan Huang (7):
  dt-bindings: usb: Add Mediatek MT6370 TCPC binding
  dt-bindings: leds: mt6370: Add Mediatek mt6370 indicator
  dt-bindings: backlight: Add Mediatek MT6370 backlight binding
  dt-bindings: mfd: Add Mediatek MT6370 binding
  mfd: mt6370: Add Mediatek MT6370 support
  usb: typec: tcpci_mt6370: Add Mediatek MT6370 tcpci driver
  regulator: mt6370: Add mt6370 DisplayBias and VibLDO support

ChiaEn Wu (4):
  dt-bindings: power: supply: Add Mediatek MT6370 Charger binding
  iio: adc: mt6370: Add Mediatek MT6370 support
  power: supply: mt6370: Add Mediatek MT6370 charger driver
  video: backlight: mt6370: Add Mediatek MT6370 support

 .../backlight/mediatek,mt6370-backlight.yaml  |  110 ++
 .../leds/mediatek,mt6370-flashlight.yaml  |   48 +
 .../leds/mediatek,mt6370-indicator.yaml   |   57 +
 .../bindings/mfd/mediatek,mt6370.yaml |  282 
 .../power/supply/mediatek,mt6370-charger.yaml |   60 +
 .../bindings/usb/mediatek,mt6370-tcpc.yaml|   35 +
 drivers/iio/adc/Kconfig   |9 +
 drivers/iio/adc/Makefile  |1 +
 drivers/iio/adc/mt6370-adc.c  |  257 
 drivers/leds/Kconfig  |   11 +
 drivers/leds/Makefile |1 +
 drivers/leds/flash/Kconfig|9 +
 drivers/leds/flash/Makefile   |1 +
 drivers/leds/flash/leds-mt6370-flash.c|  665 ++
 drivers/leds/leds-mt6370.c|  994 +++
 drivers/mfd/Kconfig   |   13 +
 drivers/mfd/Makefile  |1 +
 drivers/mfd/mt6370.c  |  273 
 drivers/power/supply/Kconfig  |   11 +
 drivers/power/supply/Makefile |1 +
 drivers/power/supply/mt6370-charger.c | 1132 +
 drivers/regulator/Kconfig |8 +
 drivers/regulator/Makefile|1 +
 drivers/regulator/mt6370-regulator.c  |  389 ++
 drivers/usb/typec/tcpm/Kconfig|8 +
 drivers/usb/typec/tcpm/Makefile   |1 +
 drivers/usb/typec/tcpm/tcpci_mt6370.c |  212 +++
 drivers/video/backlight/Kconfig   |8 +
 drivers/video/backlight/Makefile  |1 +
 drivers/video/backlight/mt6370-backlight.c|  338 +
 .../dt-bindings/iio/adc/mediatek,mt6370_adc.h |   18 +
 include/dt-bindings/mfd/mediatek,mt6370.h |   83 ++
 32 files changed, 5038 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/leds/backlight/mediatek,mt6370-backlight.yaml
 create mode 100644 
Documentation/devicetree/bindings/leds/mediatek,mt6370-flashlight.yaml
 create mode 100644 
Documentation/devicetree/bindings/leds/mediatek,mt6370-indicator.yaml
 create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
 create mode 100644 
Documentation/devicetree/bindings/power/supply/mediatek,mt6370-charger.yaml
 create mode 100644 
Documentation/devicetree/bindings/usb/mediatek,mt6370-tcpc.yaml
 create mode 100644 drivers/iio/adc/mt6370-adc.c
 create mode 100644 drivers/leds/flash/leds-mt6370-flash.c
 create mode 100644 drivers/leds/leds-mt6370.c
 create mode 100644 drivers/mfd/mt6370.c
 create mode 100644 drivers/power/supply/mt6370-charger.c
 create mode 100644 drivers/regulator/mt6370-regulator.c
 create mode 100644 drivers/usb/typec/tcpm/tcpci_mt6370.c
 create mode 100644 drivers/video/backlight/mt6370-backlight.c
 create mode 100644 include/dt-bindings/iio/adc/mediatek,mt6370_adc.h
 create mode 100644 include/dt-bindings/mfd/mediatek,mt6370.h

-- 
2.25.1



[RESEND 08/14] usb: typec: tcpci_mt6370: Add Mediatek MT6370 tcpci driver

2022-05-31 Thread ChiaEn Wu
From: ChiYuan Huang 

Add chip level mt6370 tcpci driver.

Signed-off-by: ChiYuan Huang 
---
 drivers/usb/typec/tcpm/Kconfig|   8 +
 drivers/usb/typec/tcpm/Makefile   |   1 +
 drivers/usb/typec/tcpm/tcpci_mt6370.c | 212 ++
 3 files changed, 221 insertions(+)
 create mode 100644 drivers/usb/typec/tcpm/tcpci_mt6370.c

diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig
index 557f392fe24d..f4b7363bc7e9 100644
--- a/drivers/usb/typec/tcpm/Kconfig
+++ b/drivers/usb/typec/tcpm/Kconfig
@@ -35,6 +35,14 @@ config TYPEC_MT6360
  USB Type-C. It works with Type-C Port Controller Manager
  to provide USB PD and USB Type-C functionalities.
 
+config TYPEC_TCPCI_MT6370
+   tristate "Mediatek MT6370 Type-C driver"
+   depends on MFD_MT6370
+   help
+ Mediatek MT6370 is a multi-functional IC that includes
+ USB Type-C. It works with Type-C Port Controller Manager
+ to provide USB PD and USB Type-C functionalities.
+
 config TYPEC_TCPCI_MAXIM
tristate "Maxim TCPCI based Type-C chip driver"
help
diff --git a/drivers/usb/typec/tcpm/Makefile b/drivers/usb/typec/tcpm/Makefile
index 7d499f3569fd..906d9dced8e7 100644
--- a/drivers/usb/typec/tcpm/Makefile
+++ b/drivers/usb/typec/tcpm/Makefile
@@ -6,4 +6,5 @@ typec_wcove-y   := wcove.o
 obj-$(CONFIG_TYPEC_TCPCI)  += tcpci.o
 obj-$(CONFIG_TYPEC_RT1711H)+= tcpci_rt1711h.o
 obj-$(CONFIG_TYPEC_MT6360) += tcpci_mt6360.o
+obj-$(CONFIG_TYPEC_TCPCI_MT6370)   += tcpci_mt6370.o
 obj-$(CONFIG_TYPEC_TCPCI_MAXIM)+= tcpci_maxim.o
diff --git a/drivers/usb/typec/tcpm/tcpci_mt6370.c 
b/drivers/usb/typec/tcpm/tcpci_mt6370.c
new file mode 100644
index ..ce7f5e03fd10
--- /dev/null
+++ b/drivers/usb/typec/tcpm/tcpci_mt6370.c
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "tcpci.h"
+
+#define MT6370_REG_SYSCTRL80x9B
+
+#define MT6370_AUTOIDLE_MASK   BIT(3)
+
+#define MT6370_VENDOR_ID   0x29CF
+#define MT6370_TCPC_DID_A  0x2170
+
+struct mt6370_priv {
+   struct device *dev;
+   struct regulator *vbus;
+   struct tcpci *tcpci;
+   struct tcpci_data tcpci_data;
+   int irq;
+};
+
+static const struct reg_sequence mt6370_reg_init[] = {
+   REG_SEQ(0xA0, 0x1, 1000),
+   REG_SEQ(0x81, 0x38, 0),
+   REG_SEQ(0x82, 0x82, 0),
+   REG_SEQ(0xBA, 0xFC, 0),
+   REG_SEQ(0xBB, 0x50, 0),
+   REG_SEQ(0x9E, 0x8F, 0),
+   REG_SEQ(0xA1, 0x5, 0),
+   REG_SEQ(0xA2, 0x4, 0),
+   REG_SEQ(0xA3, 0x4A, 0),
+   REG_SEQ(0xA4, 0x01, 0),
+   REG_SEQ(0x95, 0x01, 0),
+   REG_SEQ(0x80, 0x71, 0),
+   REG_SEQ(0x9B, 0x3A, 1000)
+};
+
+static int mt6370_tcpc_init(struct tcpci *tcpci, struct tcpci_data *data)
+{
+   u16 did;
+   int ret;
+
+   ret = regmap_register_patch(data->regmap, mt6370_reg_init,
+   ARRAY_SIZE(mt6370_reg_init));
+   if (ret)
+   return ret;
+
+   ret = regmap_raw_read(data->regmap, TCPC_BCD_DEV, &did, sizeof(u16));
+   if (ret)
+   return ret;
+
+   if (did == MT6370_TCPC_DID_A) {
+   ret = regmap_write(data->regmap, TCPC_FAULT_CTRL, 0x80);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
+}
+
+static int mt6370_tcpc_set_vconn(struct tcpci *tcpci, struct tcpci_data *data,
+bool enable)
+{
+   return regmap_update_bits(data->regmap, MT6370_REG_SYSCTRL8,
+ MT6370_AUTOIDLE_MASK,
+ !enable ? MT6370_AUTOIDLE_MASK : 0);
+}
+
+static int mt6370_tcpc_set_vbus(struct tcpci *tcpci, struct tcpci_data *data,
+   bool source, bool sink)
+{
+   struct mt6370_priv *priv = container_of(data, struct mt6370_priv,
+   tcpci_data);
+   int ret;
+
+   ret = regulator_is_enabled(priv->vbus);
+   if (ret < 0)
+   return ret;
+
+   if (ret && !source)
+   ret = regulator_disable(priv->vbus);
+   else if (!ret && source)
+   ret = regulator_enable(priv->vbus);
+   else
+   ret = 0;
+
+   return ret;
+}
+
+static irqreturn_t mt6370_irq_handler(int irq, void *dev_id)
+{
+   struct mt6370_priv *priv = dev_id;
+
+   return tcpci_irq(priv->tcpci);
+}
+
+static int mt6370_check_vendor_info(struct mt6370_priv *priv)
+{
+   struct regmap *regmap = priv->tcpci_data.regmap;
+   u16 vid;
+   int ret;
+
+   ret = regmap_raw_read(regmap, TCPC_VENDOR_ID, &vid, sizeof(u16));
+   if (ret)
+   return ret;
+
+   if (vid != MT6370_VENDOR_ID) {
+   dev_err(priv->dev, "Vendor ID not corre

[RESEND 04/14] dt-bindings: leds: Add Mediatek MT6370 flashlight binding

2022-05-31 Thread ChiaEn Wu
From: Alice Chen 

Add Mediatek MT6370 flashlight binding documentation

Signed-off-by: Alice Chen 
---
 .../leds/mediatek,mt6370-flashlight.yaml  | 48 +++
 1 file changed, 48 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/leds/mediatek,mt6370-flashlight.yaml

diff --git 
a/Documentation/devicetree/bindings/leds/mediatek,mt6370-flashlight.yaml 
b/Documentation/devicetree/bindings/leds/mediatek,mt6370-flashlight.yaml
new file mode 100644
index ..b1b11bd3d410
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/mediatek,mt6370-flashlight.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/leds-mt6370-flashlight.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Flash LED driver for MT6370 PMIC from MediaTek Integrated.
+
+maintainers:
+  - Alice Chen 
+
+description: |
+  This module is part of the MT6370 MFD device.
+  see Documentation/devicetree/bindings/mfd/mt6370.yaml
+  Add MT6370 flash LED driver include 2-channel flash LED support Torch/Strobe 
Mode.
+
+properties:
+  compatible:
+const: mediatek,mt6370-flashlight
+
+  "#address-cells":
+const: 1
+
+  "#size-cells":
+const: 0
+
+patternProperties:
+  "^led@[0-1]$":
+type: object
+$ref: common.yaml#
+description:
+  Properties for a single flash LED.
+
+properties:
+  reg:
+description: Index of the flash LED.
+enum:
+  - 0 #Address of LED1
+  - 1 #Address of LED2
+
+unevaluatedProperties: false
+
+required:
+  - compatible
+  - "#address-cells"
+  - "#size-cells"
+
+additionalProperties: false
-- 
2.25.1



[RESEND 11/14] power: supply: mt6370: Add Mediatek MT6370 charger driver

2022-05-31 Thread ChiaEn Wu
From: ChiaEn Wu 

Add Mediatek MT6370 charger driver

Signed-off-by: ChiaEn Wu 
---
 drivers/power/supply/Kconfig  |   11 +
 drivers/power/supply/Makefile |1 +
 drivers/power/supply/mt6370-charger.c | 1132 +
 3 files changed, 1144 insertions(+)
 create mode 100644 drivers/power/supply/mt6370-charger.c

diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 1aa8323ad9f6..54d8c3ab01cc 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -619,6 +619,17 @@ config CHARGER_MT6360
  Average Input Current Regulation, Battery Temperature Sensing,
  Over-Temperature Protection, DPDM Detection for BC1.2.
 
+config CHARGER_MT6370
+   tristate "Mediatek MT6370 Charger Driver"
+   depends on MFD_MT6370
+   depends on REGULATOR
+   select LINEAR_RANGES
+   help
+ Say Y here to enable MT6370 Charger Part.
+ The device supports High-Accuracy Voltage/Current Regulation,
+ Average Input Current Regulation, Battery Temperature Sensing,
+ Over-Temperature Protection, DPDM Detection for BC1.2.
+
 config CHARGER_QCOM_SMBB
tristate "Qualcomm Switch-Mode Battery Charger and Boost"
depends on MFD_SPMI_PMIC || COMPILE_TEST
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 7f02f36aea55..8c9527643c86 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
 obj-$(CONFIG_CHARGER_MAX8998)  += max8998_charger.o
 obj-$(CONFIG_CHARGER_MP2629)   += mp2629_charger.o
 obj-$(CONFIG_CHARGER_MT6360)   += mt6360_charger.o
+obj-$(CONFIG_CHARGER_MT6370)   += mt6370-charger.o
 obj-$(CONFIG_CHARGER_QCOM_SMBB)+= qcom_smbb.o
 obj-$(CONFIG_CHARGER_BQ2415X)  += bq2415x_charger.o
 obj-$(CONFIG_CHARGER_BQ24190)  += bq24190_charger.o
diff --git a/drivers/power/supply/mt6370-charger.c 
b/drivers/power/supply/mt6370-charger.c
new file mode 100644
index ..1cfa4deeb28e
--- /dev/null
+++ b/drivers/power/supply/mt6370-charger.c
@@ -0,0 +1,1132 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MT6370_REG_CHG_CTRL1   0x111
+#define MT6370_REG_CHG_CTRL2   0x112
+#define MT6370_REG_CHG_CTRL3   0x113
+#define MT6370_REG_CHG_CTRL4   0x114
+#define MT6370_REG_CHG_CTRL5   0x115
+#define MT6370_REG_CHG_CTRL6   0x116
+#define MT6370_REG_CHG_CTRL7   0x117
+#define MT6370_REG_CHG_CTRL8   0x118
+#define MT6370_REG_CHG_CTRL9   0x119
+#define MT6370_REG_CHG_CTRL10  0x11A
+#define MT6370_REG_DEVICE_TYPE 0x122
+#define MT6370_REG_USB_STATUS1 0x127
+#define MT6370_REG_CHG_STAT0x14A
+#define MT6370_REG_FLED_EN 0x17E
+#define MT6370_REG_CHG_STAT1   0X1D0
+#define MT6370_REG_OVPCTRL_STAT0x1D8
+
+#define MT6370_VOBST_MASK  GENMASK(7, 2)
+#define MT6370_OTG_PIN_EN_MASK BIT(1)
+#define MT6370_OPA_MODE_MASK   BIT(0)
+#define MT6370_OTG_OC_MASK GENMASK(2, 0)
+
+#define MT6370_MIVR_IBUS_TH10  /* 100 mA */
+
+enum mt6370_chg_reg_field {
+   /* MT6370_REG_CHG_CTRL2 */
+   F_IINLMTSEL, F_CFO_EN, F_CHG_EN,
+   /* MT6370_REG_CHG_CTRL3 */
+   F_IAICR, F_AICR_EN, F_ILIM_EN,
+   /* MT6370_REG_CHG_CTRL4 */
+   F_VOREG,
+   /* MT6370_REG_CHG_CTRL5 */
+   F_VOBST,
+   /* MT6370_REG_CHG_CTRL6 */
+   F_VMIVR,
+   /* MT6370_REG_CHG_CTRL7 */
+   F_ICHG,
+   /* MT6370_REG_CHG_CTRL8 */
+   F_IPREC,
+   /* MT6370_REG_CHG_CTRL9 */
+   F_IEOC,
+   /* MT6370_REG_DEVICE_TYPE */
+   F_USBCHGEN,
+   /* MT6370_REG_USB_STATUS1 */
+   F_USB_STAT, F_CHGDET,
+   /* MT6370_REG_CHG_STAT */
+   F_CHG_STAT, F_BOOST_STAT, F_VBAT_LVL,
+   /* MT6370_REG_FLED_EN */
+   F_FL_STROBE,
+   /* MT6370_REG_CHG_STAT1 */
+   F_CHG_MIVR_STAT,
+   /* MT6370_REG_OVPCTRL_STAT */
+   F_UVP_D_STAT,
+   F_MAX,
+};
+
+struct mt6370_priv {
+   struct device *dev;
+   struct iio_channel *iio_adcs;
+   struct mutex attach_lock;
+   struct power_supply *psy;
+   struct power_supply_desc *psy_desc;
+   struct regmap *regmap;
+   struct regmap_field *rmap_fields[F_MAX];
+   struct regulator_dev *rdev;
+   struct workqueue_struct *wq;
+   struct work_struct bc12_work;
+   struct delayed_work mivr_dwork;
+   atomic_t attach;
+   int psy_usb_type;
+   bool pwr_rdy;
+};
+
+enum mt6370_usb_status {
+   MT6370_USB_STAT_NO_VBUS = 0,
+   MT6370_USB_STAT_VBUS_FLOW_IS_UNDER_GOING,
+   MT6370_USB_STAT_SDP,
+   MT6370_USB_STAT_SDP_NSTD,
+   MT6370_USB_STAT_DCP,
+   MT6370_U

[RESEND 13/14] leds: flashlight: mt6370: Add Mediatek MT6370 flashlight support

2022-05-31 Thread ChiaEn Wu
From: Alice Chen 

Add Mediatek MT6370 flashlight support

Signed-off-by: Alice Chen 
---
 drivers/leds/flash/Kconfig |   9 +
 drivers/leds/flash/Makefile|   1 +
 drivers/leds/flash/leds-mt6370-flash.c | 665 +
 3 files changed, 675 insertions(+)
 create mode 100644 drivers/leds/flash/leds-mt6370-flash.c

diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig
index d3eb689b193c..d38e263aaf09 100644
--- a/drivers/leds/flash/Kconfig
+++ b/drivers/leds/flash/Kconfig
@@ -90,4 +90,13 @@ config LEDS_SGM3140
  This option enables support for the SGM3140 500mA Buck/Boost Charge
  Pump LED Driver.
 
+config LEDS_MT6370_FLASHLIGHT
+   tristate "Flash LED Support for Mediatek MT6370 PMIC"
+   depends on LEDS_CLASS
+   depends on MFD_MT6370
+   help
+ Support 2 channels and torch/strobe mode.
+ Say Y here to enable support for
+ MT6370_FLASH_LED device.
+
 endif # LEDS_CLASS_FLASH
diff --git a/drivers/leds/flash/Makefile b/drivers/leds/flash/Makefile
index 0acbddc0b91b..4c4c1710f506 100644
--- a/drivers/leds/flash/Makefile
+++ b/drivers/leds/flash/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_LEDS_MAX77693) += leds-max77693.o
 obj-$(CONFIG_LEDS_RT4505)  += leds-rt4505.o
 obj-$(CONFIG_LEDS_RT8515)  += leds-rt8515.o
 obj-$(CONFIG_LEDS_SGM3140) += leds-sgm3140.o
+obj-$(CONFIG_LEDS_MT6370_FLASHLIGHT)   += leds-mt6370-flash.o
diff --git a/drivers/leds/flash/leds-mt6370-flash.c 
b/drivers/leds/flash/leds-mt6370-flash.c
new file mode 100644
index ..8f6796aae3e1
--- /dev/null
+++ b/drivers/leds/flash/leds-mt6370-flash.c
@@ -0,0 +1,665 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+enum {
+   MT6370_LED_FLASH1,
+   MT6370_LED_FLASH2,
+   MT6370_MAX_LEDS
+};
+
+/* Virtual definition for multicolor */
+
+#define MT6370_REG_FLEDEN  0x17E
+#define MT6370_REG_STRBTO  0x173
+#define MT6370_REG_CHGSTAT20x1D1
+#define MT6370_REG_FLEDSTAT1   0x1D9
+#defineMT6370_REG_FLEDISTRB(_id)   (0x174 + 4 * _id)
+#define MT6370_REG_FLEDITOR(_id)   (0x175 + 4 * _id)
+#define MT6370_ITORCH_MASK GENMASK(4, 0)
+#define MT6370_ISTROBE_MASKGENMASK(6, 0)
+#define MT6370_STRBTO_MASK GENMASK(6, 0)
+#define MT6370_TORCHEN_MASKBIT(3)
+#define MT6370_STROBEN_MASKBIT(2)
+#define MT6370_FLCSEN_MASK(_id)BIT(MT6370_LED_FLASH2 - _id)
+#define MT6370_FLCSEN_MASK_ALL (BIT(0) | BIT(1))
+#define MT6370_FLEDCHGVINOVP_MASK  BIT(3)
+#define MT6370_FLED1STRBTO_MASKBIT(11)
+#define MT6370_FLED2STRBTO_MASKBIT(10)
+#define MT6370_FLED1STRB_MASK  BIT(9)
+#define MT6370_FLED2STRB_MASK  BIT(8)
+#define MT6370_FLED1SHORT_MASK BIT(7)
+#define MT6370_FLED2SHORT_MASK BIT(6)
+#define MT6370_FLEDLVF_MASKBIT(3)
+
+#define MT6370_LED_JOINT   2
+#define MT6370_RANGE_FLED_REG  4
+#define MT6370_ITORCH_MINUA25000
+#define MT6370_ITORCH_STEPUA   12500
+#define MT6370_ITORCH_MAXUA40
+#define MT6370_ITORCH_DOUBLE_MAXUA 80
+#define MT6370_ISTRB_MINUA 5
+#define MT6370_ISTRB_STEPUA12500
+#define MT6370_ISTRB_MAXUA 150
+#define MT6370_ISTRB_DOUBLE_MAXUA  300
+#define MT6370_STRBTO_MINUS64000
+#define MT6370_STRBTO_STEPUS   32000
+#define MT6370_STRBTO_MAXUS2432000
+
+#define STATE_OFF  0
+#define STATE_KEEP 1
+#define STATE_ON   2
+
+struct mt6370_led {
+   struct led_classdev_flash flash;
+   struct v4l2_flash *v4l2_flash;
+   struct mt6370_priv *priv;
+   u32 led_no;
+   u32 default_state;
+};
+
+struct mt6370_priv {
+   struct device *dev;
+   struct regmap *regmap;
+   struct mutex lock;
+   unsigned int fled_strobe_used;
+   unsigned int fled_torch_used;
+   unsigned int leds_active;
+   unsigned int leds_count;
+   struct mt6370_led leds[];
+};
+
+static int mt6370_torch_brightness_set(struct led_classdev *lcdev,
+  enum led_brightness level)
+{
+   struct mt6370_led *led =
+container_of(lcdev, struct mt6370_led, flash.led_cdev);
+   struct mt6370_priv *priv = led->priv;
+   u32 led_enable_mask = (led->led_no == MT6370_LED_JOINT) ?
+ MT6370_FLCSEN_MASK_ALL :
+ MT6370_FLCSEN_MASK(led->led_no);
+   u32 enable_mask = MT6370_TORCHEN_MASK | led_enable_mask;
+   u32 val = level ? led_enable_mask : 0;
+   u32 prev = priv->fled_torch_used, curr;
+   int ret, i;
+
+   mutex_lock(&priv->lock);
+
+ 

[RESEND 09/14] regulator: mt6370: Add mt6370 DisplayBias and VibLDO support

2022-05-31 Thread ChiaEn Wu
From: ChiYuan Huang 

Add mt6370 DisplayBias and VibLDO support.

Signed-off-by: ChiYuan Huang 
---
 drivers/regulator/Kconfig|   8 +
 drivers/regulator/Makefile   |   1 +
 drivers/regulator/mt6370-regulator.c | 389 +++
 3 files changed, 398 insertions(+)
 create mode 100644 drivers/regulator/mt6370-regulator.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index cbe0f96ca342..dcb6866dab53 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -804,6 +804,14 @@ config REGULATOR_MT6360
  2-channel buck with Thermal Shutdown and Overload Protection
  6-channel High PSRR and Low Dropout LDO.
 
+config REGULATOR_MT6370
+   tristate "MT6370 SubPMIC Regulator"
+   depends on MFD_MT6370
+   help
+ Say Y here to enable MT6370 regulator support.
+ This driver support the control for DisplayBias voltages and one
+ general purpose LDO which commonly used to drive the vibrator.
+
 config REGULATOR_MT6380
tristate "MediaTek MT6380 PMIC"
depends on MTK_PMIC_WRAP
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 8d3ee8b6d41d..f1cbff21843e 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -97,6 +97,7 @@ obj-$(CONFIG_REGULATOR_MT6323)+= mt6323-regulator.o
 obj-$(CONFIG_REGULATOR_MT6358) += mt6358-regulator.o
 obj-$(CONFIG_REGULATOR_MT6359) += mt6359-regulator.o
 obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o
+obj-$(CONFIG_REGULATOR_MT6370) += mt6370-regulator.o
 obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
 obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
 obj-$(CONFIG_REGULATOR_MTK_DVFSRC) += mtk-dvfsrc-regulator.o
diff --git a/drivers/regulator/mt6370-regulator.c 
b/drivers/regulator/mt6370-regulator.c
new file mode 100644
index ..949b2c7b5556
--- /dev/null
+++ b/drivers/regulator/mt6370-regulator.c
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+enum {
+   MT6370_IDX_DSVBOOST = 0,
+   MT6370_IDX_DSVPOS,
+   MT6370_IDX_DSVNEG,
+   MT6370_IDX_VIBLDO,
+   MT6370_MAX_IDX
+};
+
+#define MT6370_REG_LDO_CFG 0x180
+#define MT6370_REG_LDO_VOUT0x181
+#define MT6370_REG_DB_CTRL10x1B0
+#define MT6370_REG_DB_CTRL20x1B1
+#define MT6370_REG_DB_VBST 0x1B2
+#define MT6370_REG_DB_VPOS 0x1B3
+#define MT6370_REG_DB_VNEG 0x1B4
+#define MT6370_REG_LDO_STAT0x1DC
+#define MT6370_REG_DB_STAT 0x1DF
+
+#define MT6370_LDOOMS_MASK BIT(7)
+#define MT6370_LDOEN_MASK  BIT(7)
+#define MT6370_LDOVOUT_MASKGENMASK(3, 0)
+#define MT6370_DBPERD_MASK (BIT(7) | BIT(4))
+#define MT6370_DBEXTEN_MASKBIT(0)
+#define MT6370_DBVPOSEN_MASK   BIT(6)
+#define MT6370_DBVPOSDISG_MASK BIT(5)
+#define MT6370_DBVNEGEN_MASK   BIT(3)
+#define MT6370_DBVNEGDISG_MASK BIT(2)
+#define MT6370_DBALLON_MASK(MT6370_DBVPOSEN_MASK | MT6370_DBVNEGEN_MASK)
+#define MT6370_DBSLEW_MASK GENMASK(7, 6)
+#define MT6370_DBVOUT_MASK GENMASK(5, 0)
+#define MT6370_LDOOC_EVT_MASK  BIT(7)
+#define MT6370_POSSCP_EVT_MASK BIT(7)
+#define MT6370_NEGSCP_EVT_MASK BIT(6)
+#define MT6370_BSTOCP_EVT_MASK BIT(5)
+#define MT6370_POSOCP_EVT_MASK BIT(4)
+#define MT6370_NEGOCP_EVT_MASK BIT(3)
+
+#define MT6370_LDO_MINUV   160
+#define MT6370_LDO_STPUV   20
+#define MT6370_LDO_N_VOLT  13
+#define MT6370_DBVBOOST_MINUV  400
+#define MT6370_DBVBOOST_STPUV  5
+#define MT6370_DBVBOOST_N_VOLT 45
+#define MT6370_DBVOUT_MINUV400
+#define MT6370_DBVOUT_STPUV5
+#define MT6370_DBVOUT_N_VOLT   41
+
+struct mt6370_priv {
+   struct device *dev;
+   struct regmap *regmap;
+   struct regulator_dev *rdev[MT6370_MAX_IDX];
+   bool use_external_ctrl;
+};
+
+static const unsigned int mt6370_vpos_ramp_tbl[] = { 8540, 5840, 4830, 3000 };
+static const unsigned int mt6370_vneg_ramp_tbl[] = { 10090, 6310, 5050, 3150 };
+
+static int mt6370_get_error_flags(struct regulator_dev *rdev,
+ unsigned int *flags)
+{
+   struct regmap *regmap = rdev_get_regmap(rdev);
+   unsigned int stat_reg, stat, rpt_flags = 0;
+   int rid = rdev_get_id(rdev), ret;
+
+   if (rid == MT6370_IDX_VIBLDO)
+   stat_reg = MT6370_REG_LDO_STAT;
+   else
+   stat_reg = MT6370_REG_DB_STAT;
+
+   ret = regmap_read(regmap, stat_reg, &stat);
+   if (ret)
+   return ret;
+
+   switch (rid) {
+   case MT6370_IDX_DSVBOOST:
+   if (stat & MT6370_BSTOCP_EVT_MASK)
+   rpt_flags |= REGULATOR_ERROR_OVER_CURRENT;
+   break;
+   case MT6370_IDX_DSVPOS:
+   if (stat & MT6370_POSSCP_EVT_MASK)
+   rpt_flags |= REGULATOR_ERROR_UNDER_VOLTAGE;
+
+   if (stat & MT6370_POSOCP_EVT_MASK)
+  

[RESEND 14/14] video: backlight: mt6370: Add Mediatek MT6370 support

2022-05-31 Thread ChiaEn Wu
From: ChiaEn Wu 

Add Mediatek MT6370 Backlight support.

Signed-off-by: ChiaEn Wu 
---
 drivers/video/backlight/Kconfig|   8 +
 drivers/video/backlight/Makefile   |   1 +
 drivers/video/backlight/mt6370-backlight.c | 338 +
 3 files changed, 347 insertions(+)
 create mode 100644 drivers/video/backlight/mt6370-backlight.c

diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index a003e02e13ce..d9868fbe7488 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -268,6 +268,14 @@ config BACKLIGHT_MAX8925
  If you have a LCD backlight connected to the WLED output of MAX8925
  WLED output, say Y here to enable this driver.
 
+config BACKLIGHT_MT6370
+   tristate "Mediatek MT6370 Backlight Driver"
+   depends on MFD_MT6370
+   help
+ Say Y here to enable MT6370 Backlight support.
+ It's commonly used to drive the display WLED. There're 4 channels
+ inisde, and each channel can provide up to 30mA current.
+
 config BACKLIGHT_APPLE
tristate "Apple Backlight Driver"
depends on X86 && ACPI
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index cae2c83422ae..e815f3f1deff 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_BACKLIGHT_LP855X)+= lp855x_bl.o
 obj-$(CONFIG_BACKLIGHT_LP8788) += lp8788_bl.o
 obj-$(CONFIG_BACKLIGHT_LV5207LP)   += lv5207lp.o
 obj-$(CONFIG_BACKLIGHT_MAX8925)+= max8925_bl.o
+obj-$(CONFIG_BACKLIGHT_MT6370) += mt6370-backlight.o
 obj-$(CONFIG_BACKLIGHT_OMAP1)  += omap1_bl.o
 obj-$(CONFIG_BACKLIGHT_PANDORA)+= pandora_bl.o
 obj-$(CONFIG_BACKLIGHT_PCF50633)   += pcf50633-backlight.o
diff --git a/drivers/video/backlight/mt6370-backlight.c 
b/drivers/video/backlight/mt6370-backlight.c
new file mode 100644
index ..f8a8d33203ed
--- /dev/null
+++ b/drivers/video/backlight/mt6370-backlight.c
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MT6370_REG_DEV_INFO0x100
+#define MT6370_REG_BL_EN   0x1A0
+#define MT6370_REG_BL_BSTCTRL  0x1A1
+#define MT6370_REG_BL_PWM  0x1A2
+#define MT6370_REG_BL_DIM2 0x1A4
+
+#define MT6370_VENID_MASK  GENMASK(7, 4)
+#define MT6370_BL_EXT_EN_MASK  BIT(7)
+#define MT6370_BL_EN_MASK  BIT(6)
+#define MT6370_BL_CONFIG_MASK  BIT(0)
+#define MT6370_BL_CH_MASK  GENMASK(5, 2)
+#define MT6370_BL_DIM2_MASKGENMASK(2, 0)
+#define MT6370_BL_DUMMY_6372_MASK  GENMASK(2, 0)
+#define MT6370_BL_DIM2_6372_SHIFT  3
+#define MT6370_BL_PWM_EN_MASK  BIT(7)
+#define MT6370_BL_PWM_HYS_EN_MASK  BIT(2)
+#define MT6370_BL_PWM_HYS_SEL_MASK GENMASK(1, 0)
+#define MT6370_BL_OVP_EN_MASK  BIT(7)
+#define MT6370_BL_OVP_SEL_MASK GENMASK(6, 5)
+#define MT6370_BL_OC_EN_MASK   BIT(3)
+#define MT6370_BL_OC_SEL_MASK  GENMASK(2, 1)
+
+#define MT6370_BL_MAX_BRIGHTNESS   2048
+
+enum {
+   MT6370_VID_COMMON = 0,
+   MT6370_VID_6372,
+   MT6370_VID_MAX,
+};
+
+enum mt6370_prop_type {
+   MT6370_PARSE_TYPE_BOOL = 0,
+   MT6370_PARSE_TYPE_U8,
+   MT6370_PARSE_TYPE_MAX,
+};
+
+struct mt6370_priv {
+   int vid_type;
+   struct backlight_device *bl;
+   struct device *dev;
+   struct gpio_desc *enable_gpio;
+   struct regmap *regmap;
+};
+
+static int mt6370_bl_update_status(struct backlight_device *bl_dev)
+{
+   struct mt6370_priv *priv = bl_get_data(bl_dev);
+   int brightness = backlight_get_brightness(bl_dev);
+   unsigned int enable_val;
+   u8 brightness_val[2];
+   int ret;
+
+   if (brightness) {
+   brightness_val[0] = (brightness - 1) & MT6370_BL_DIM2_MASK;
+   brightness_val[1] = (brightness - 1)
+   >> fls(MT6370_BL_DIM2_MASK);
+
+   if (priv->vid_type == MT6370_VID_6372) {
+   brightness_val[0] <<= MT6370_BL_DIM2_6372_SHIFT;
+   brightness_val[0] |= MT6370_BL_DUMMY_6372_MASK;
+   }
+
+   ret = regmap_raw_write(priv->regmap, MT6370_REG_BL_DIM2,
+  brightness_val, sizeof(brightness_val));
+   if (ret)
+   return ret;
+   }
+
+   if (priv->enable_gpio)
+   gpiod_set_value(priv->enable_gpio, brightness ? 1 : 0);
+
+   enable_val = brightness ? MT6370_BL_EN_MASK : 0;
+   return regmap_update_bits(priv->regmap, MT6370_REG_BL_EN,
+ MT6370_BL_EN_MASK, enable_val);
+}
+
+static int mt6370_bl_get_brightness(struct backlight_device *bl_dev)
+{
+  

[RESEND 12/14] leds: mt6370: Add Mediatek MT6370 Indicator support

2022-05-31 Thread ChiaEn Wu
From: Alice Chen 

Add Mediatek MT6370 Indicator support

Signed-off-by: Alice Chen 
---
 drivers/leds/Kconfig   |  11 +
 drivers/leds/Makefile  |   1 +
 drivers/leds/leds-mt6370.c | 994 +
 3 files changed, 1006 insertions(+)
 create mode 100644 drivers/leds/leds-mt6370.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 6090e647daee..0cb2294b3431 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -244,6 +244,17 @@ config LEDS_MT6323
  This option enables support for on-chip LED drivers found on
  Mediatek MT6323 PMIC.
 
+config LEDS_MT6370_RGB
+   tristate "LED Support for Mediatek MT6370 PMIC"
+   depends on LEDS_CLASS
+   depends on MFD_MT6370
+   select LINEAR_RANGE
+   help
+ Support 4 channels and reg/pwm/breath mode.
+ Isink4 can also use as a CHG_VIN power good Indicator.
+ Say Y here to enable support for
+ MT6370_RGB_LED device.
+
 config LEDS_S3C24XX
tristate "LED Support for Samsung S3C24XX GPIO LEDs"
depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index e58ecb36360f..b641fd83f49a 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o
 obj-$(CONFIG_LEDS_MLXCPLD) += leds-mlxcpld.o
 obj-$(CONFIG_LEDS_MLXREG)  += leds-mlxreg.o
 obj-$(CONFIG_LEDS_MT6323)  += leds-mt6323.o
+obj-$(CONFIG_LEDS_MT6370_RGB)  += leds-mt6370.o
 obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
 obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o
 obj-$(CONFIG_LEDS_NIC78BX) += leds-nic78bx.o
diff --git a/drivers/leds/leds-mt6370.c b/drivers/leds/leds-mt6370.c
new file mode 100644
index ..54f654d4f4fc
--- /dev/null
+++ b/drivers/leds/leds-mt6370.c
@@ -0,0 +1,994 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+enum {
+   MT6370_LED_ISNK1 = 0,
+   MT6370_LED_ISNK2,
+   MT6370_LED_ISNK3,
+   MT6370_LED_ISNK4,
+   MT6370_MAX_LEDS
+};
+
+enum mt6370_led_mode {
+   MT6370_LED_PWM_MODE = 0,
+   MT6370_LED_BREATH_MODE,
+   MT6370_LED_REG_MODE,
+   MT6370_LED_MAX_MODE
+};
+
+enum mt6370_led_field {
+   F_RGB_EN = 0,
+   F_CHGIND_EN,
+   F_LED1_CURR,
+   F_LED2_CURR,
+   F_LED3_CURR,
+   F_LED4_CURR,
+   F_LED1_MODE,
+   F_LED2_MODE,
+   F_LED3_MODE,
+   F_LED4_MODE,
+   F_LED1_DUTY,
+   F_LED2_DUTY,
+   F_LED3_DUTY,
+   F_LED4_DUTY,
+   F_LED1_FREQ,
+   F_LED2_FREQ,
+   F_LED3_FREQ,
+   F_LED4_FREQ,
+   F_MAX_FIELDS
+};
+
+enum mt6370_led_ranges {
+   R_LED123_CURR = 0,
+   R_LED4_CURR,
+   R_LED_TRFON,
+   R_LED_TOFF,
+   R_MAX_RANGES,
+};
+
+enum mt6370_pattern {
+   P_LED_TR1 = 0,
+   P_LED_TR2,
+   P_LED_TF1,
+   P_LED_TF2,
+   P_LED_TON,
+   P_LED_TOFF,
+   P_MAX_PATTERNS
+};
+
+#define MT6370_REG_DEV_INFO0x100
+#define MT6370_REG_RGB1_DIM0x182
+#define MT6370_REG_RGB2_DIM0x183
+#define MT6370_REG_RGB3_DIM0x184
+#define MT6370_REG_RGB_EN  0x185
+#define MT6370_REG_RGB1_ISNK   0x186
+#define MT6370_REG_RGB2_ISNK   0x187
+#define MT6370_REG_RGB3_ISNK   0x188
+#define MT6370_REG_RGB1_TR 0x189
+#define MT6370_REG_RGB_CHRIND_DIM  0x192
+#define MT6370_REG_RGB_CHRIND_CTRL 0x193
+#define MT6370_REG_RGB_CHRIND_TR   0x194
+
+#define MT6372_REG_RGB_EN  0x182
+#define MT6372_REG_RGB1_ISNK   0x183
+#define MT6372_REG_RGB2_ISNK   0x184
+#define MT6372_REG_RGB3_ISNK   0x185
+#define MT6372_REG_RGB4_ISNK   0x186
+#define MT6372_REG_RGB1_DIM0x187
+#define MT6372_REG_RGB2_DIM0x188
+#define MT6372_REG_RGB3_DIM0x189
+#define MT6372_REG_RGB4_DIM0x18A
+#define MT6372_REG_RGB12_FREQ  0x18B
+#define MT6372_REG_RGB34_FREQ  0x18C
+#define MT6372_REG_RGB1_TR 0x18D
+
+#define MT6370_VENID_MASK  GENMASK(7, 4)
+#define MT6370_CHEN_BIT(id)BIT(MT6370_LED_ISNK4 - id)
+#define MT6370_VIRTUAL_MULTICOLOR  5
+#define MC_CHANNEL_NUM 3
+#define MT6370_PWM_DUTY31
+#define MT6372_PMW_DUTY255
+
+#define STATE_OFF  0
+#define STATE_KEEP 1
+#define STATE_ON   2
+
+struct mt6370_led {
+   union {
+   stru

[RESEND 10/14] iio: adc: mt6370: Add Mediatek MT6370 support

2022-05-31 Thread ChiaEn Wu
From: ChiaEn Wu 

Add Mediatek MT6370 ADC support.

Signed-off-by: ChiaEn Wu 
---
 drivers/iio/adc/Kconfig  |   9 ++
 drivers/iio/adc/Makefile |   1 +
 drivers/iio/adc/mt6370-adc.c | 257 +++
 3 files changed, 267 insertions(+)
 create mode 100644 drivers/iio/adc/mt6370-adc.c

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 71ab0a06aa82..d7932dd9b773 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -737,6 +737,15 @@ config MEDIATEK_MT6360_ADC
  is used in smartphones and tablets and supports a 11 channel
  general purpose ADC.
 
+config MEDIATEK_MT6370_ADC
+   tristate "Mediatek MT6370 ADC driver"
+   depends on MFD_MT6370
+   help
+ Say Y here to enable MT6370 ADC support.
+ Integrated for System Monitoring includes
+ is used in smartphones and tablets and supports a 9 channel
+ general purpose ADC.
+
 config MEDIATEK_MT6577_AUXADC
tristate "MediaTek AUXADC driver"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 39d806f6d457..0ce285c7e2d0 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o
 obj-$(CONFIG_MCP3422) += mcp3422.o
 obj-$(CONFIG_MCP3911) += mcp3911.o
 obj-$(CONFIG_MEDIATEK_MT6360_ADC) += mt6360-adc.o
+obj-$(CONFIG_MEDIATEK_MT6370_ADC) += mt6370-adc.o
 obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o
 obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
 obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
diff --git a/drivers/iio/adc/mt6370-adc.c b/drivers/iio/adc/mt6370-adc.c
new file mode 100644
index ..3320ebca17ad
--- /dev/null
+++ b/drivers/iio/adc/mt6370-adc.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MT6370_REG_CHG_CTRL3   0x113 /* AICR */
+#define MT6370_REG_CHG_CTRL7   0x117 /* ICHG */
+#define MT6370_REG_CHG_ADC 0x121
+#define MT6370_REG_ADC_DATA_H  0x14C
+
+#define MT6370_ADC_START_MASK  BIT(0)
+#define MT6370_ADC_IN_SEL_MASK GENMASK(7, 4)
+#define MT6370_AICR_ICHG_MASK  GENMASK(7, 2)
+
+#define MT6370_ADC_CHAN_SHIFT  4
+
+#define MT6370_AICR_400MA  0x6
+#define MT6370_ICHG_500MA  0x4
+#define MT6370_ICHG_900MA  0x8
+
+#define ADC_CONV_TIME_US   35000
+#define ADC_CONV_POLLING_TIME  1000
+
+struct mt6370_adc_data {
+   struct device *dev;
+   struct regmap *regmap;
+   struct mutex lock;
+};
+
+static int mt6370_adc_read_channel(struct mt6370_adc_data *priv, int chan,
+  unsigned long addr, int *val)
+{
+   __be16 be_val;
+   unsigned int reg_val;
+   int ret;
+
+   mutex_lock(&priv->lock);
+
+   reg_val = MT6370_ADC_START_MASK | (addr << MT6370_ADC_CHAN_SHIFT);
+   ret = regmap_write(priv->regmap, MT6370_REG_CHG_ADC, reg_val);
+   if (ret)
+   goto adc_unlock;
+
+   msleep(ADC_CONV_TIME_US / 1000);
+
+   ret = regmap_read_poll_timeout(priv->regmap,
+  MT6370_REG_CHG_ADC, reg_val,
+  !(reg_val & MT6370_ADC_START_MASK),
+  ADC_CONV_POLLING_TIME,
+  ADC_CONV_TIME_US * 3);
+   if (ret) {
+   if (ret == -ETIMEDOUT)
+   dev_err(priv->dev, "Failed to wait adc conversion\n");
+   goto adc_unlock;
+   }
+
+   ret = regmap_raw_read(priv->regmap, MT6370_REG_ADC_DATA_H,
+ &be_val, sizeof(be_val));
+   if (ret)
+   goto adc_unlock;
+
+   *val = be16_to_cpu(be_val);
+   ret = IIO_VAL_INT;
+
+adc_unlock:
+   mutex_unlock(&priv->lock);
+
+   return ret;
+}
+
+static int mt6370_adc_read_scale(struct mt6370_adc_data *priv,
+int chan, int *val1, int *val2)
+{
+   unsigned int reg_val;
+   int ret;
+
+   switch (chan) {
+   case MT6370_CHAN_VBAT:
+   case MT6370_CHAN_VSYS:
+   case MT6370_CHAN_CHG_VDDP:
+   *val1 = 5000;
+   return IIO_VAL_INT;
+   case MT6370_CHAN_IBUS:
+   ret = regmap_read(priv->regmap, MT6370_REG_CHG_CTRL3, ®_val);
+   if (ret)
+   return ret;
+
+   reg_val = FIELD_GET(MT6370_AICR_ICHG_MASK, reg_val);
+   if (reg_val < MT6370_AICR_400MA)
+   *val1 = 33500;
+   else
+   *val1 = 5;
+
+   return IIO_VAL_INT;
+   case MT6370_CHAN_IBAT:
+   ret = regmap_read(priv->regmap, MT6370_REG_CHG_CTRL7, ®_val);
+   if (ret)
+   return ret;
+
+   

[RESEND 02/14] dt-bindings: power: supply: Add Mediatek MT6370 Charger binding

2022-05-31 Thread ChiaEn Wu
From: ChiaEn Wu 

Add Mediatek MT6370 Charger binding documentation.

Signed-off-by: ChiaEn Wu 
---
 .../power/supply/mediatek,mt6370-charger.yaml | 60 +++
 1 file changed, 60 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/power/supply/mediatek,mt6370-charger.yaml

diff --git 
a/Documentation/devicetree/bindings/power/supply/mediatek,mt6370-charger.yaml 
b/Documentation/devicetree/bindings/power/supply/mediatek,mt6370-charger.yaml
new file mode 100644
index ..9d5c4487ca9c
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/power/supply/mediatek,mt6370-charger.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/supply/mediatek,mt6370-charger.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT6370 Battery Charger
+
+maintainers:
+  - ChiaEn Wu 
+
+description: |
+  This module is part of the MT6370 MFD device.
+  Provides Battery Charger, Boost for OTG devices and BC1.2 detection.
+
+properties:
+  compatible:
+const: mediatek,mt6370-charger
+
+  interrupts:
+description: |
+  Specify what irqs are needed to be handled by MT6370 Charger driver. IRQ
+  "MT6370_IRQ_CHG_MIVR", "MT6370_IRQ_ATTACH" and "MT6370_IRQ_OVPCTRL_UVP_D"
+  are required.
+items:
+  - description: BC1.2 done irq for mt6370 charger
+  - description: usb plug in irq for mt6370 charger
+  - description: mivr irq for mt6370 charger
+
+  interrupt-names:
+items:
+  - const: attach_i
+  - const: uvp_d_evt
+  - const: mivr
+
+  io-channels:
+description: |
+  Use ADC channel to read vbus, ibus, ibat, etc., info. Ibus ADC channel
+  is required.
+
+  usb-otg-vbus:
+type: object
+description: OTG boost regulator.
+$ref: /schemas/regulator/regulator.yaml#
+
+properties:
+  enable-gpio:
+maxItems: 1
+description: |
+  Specify a valid 'enable' gpio for the regulator and it's optional
+
+required:
+  - compatible
+  - interrupts
+  - interrupt-names
+  - io-channels
+
+additionalProperties: false
+
+...
-- 
2.25.1



[RESEND 01/14] dt-bindings: usb: Add Mediatek MT6370 TCPC binding

2022-05-31 Thread ChiaEn Wu
From: ChiYuan Huang 

Add Mediatek MT6370 TCPC binding documentation.

Signed-off-by: ChiYuan Huang 
---
 .../bindings/usb/mediatek,mt6370-tcpc.yaml| 35 +++
 1 file changed, 35 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/usb/mediatek,mt6370-tcpc.yaml

diff --git a/Documentation/devicetree/bindings/usb/mediatek,mt6370-tcpc.yaml 
b/Documentation/devicetree/bindings/usb/mediatek,mt6370-tcpc.yaml
new file mode 100644
index ..49316633f92f
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/mediatek,mt6370-tcpc.yaml
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/usb/mediatek,mt6370-tcpc.yaml#";
+$schema: "http://devicetree.org/meta-schemas/core.yaml#";
+
+title: Mediatek MT6370 Type-C Port Switch and Power Delivery controller DT 
bindings
+
+maintainers:
+  - ChiYuan Huang 
+
+description: |
+  Mediatek MT6370 is a multi-functional device. It integrates charger, ADC, 
flash, RGB indicators,
+  regulators (DSV/VIBLDO), and TypeC Port Switch with Power Delivery 
controller.
+  This document only describes MT6370 Type-C Port Switch and Power Delivery 
controller.
+
+properties:
+  compatible:
+enum:
+  - mediatek,mt6370-tcpc
+
+  interrupts:
+maxItems: 1
+
+  connector:
+type: object
+$ref: /schemas/connector/usb-connector.yaml#
+description:
+  Properties for usb c connector.
+
+additionalProperties: false
+
+required:
+  - compatible
+  - interrupts
-- 
2.25.1



[RESEND 03/14] dt-bindings: leds: mt6370: Add Mediatek mt6370 indicator

2022-05-31 Thread ChiaEn Wu
From: ChiYuan Huang 

Add Mediatek mt6370 indicator documentation.

Signed-off-by: ChiYuan Huang 
---
 .../leds/mediatek,mt6370-indicator.yaml   | 57 +++
 1 file changed, 57 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/leds/mediatek,mt6370-indicator.yaml

diff --git 
a/Documentation/devicetree/bindings/leds/mediatek,mt6370-indicator.yaml 
b/Documentation/devicetree/bindings/leds/mediatek,mt6370-indicator.yaml
new file mode 100644
index ..823be3add097
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/mediatek,mt6370-indicator.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/mediatek,mt6370-indicator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LED driver for MT6370 PMIC from MediaTek Integrated.
+
+maintainers:
+  - Alice Chen 
+
+description: |
+  This module is part of the MT6370 MFD device.
+  see Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
+  Add MT6370 LED driver include 4-channel RGB LED support Register/PWM/Breath 
Mode
+
+properties:
+  compatible:
+const: mediatek,mt6370-indicator
+
+  "#address-cells":
+const: 1
+
+  "#size-cells":
+const: 0
+
+patternProperties:
+  "^(multi-)?led@[0-3]$":
+description: |
+  Properties for a single LED.
+$ref: common.yaml#
+type: object
+
+properties:
+  reg:
+description: |
+  Index of the LED.
+enum:
+  - 0 # LED output ISINK1
+  - 1 # LED output ISINK2
+  - 2 # LED output ISINK3
+  - 3 # LED output ISINK4
+
+  mediatek,soft-start:
+description: |
+  soft start step control, support /0.5ms/1ms/1.5ms/2ms.
+$ref: /schemas/types.yaml#/definitions/uint32
+enum: [0, 1, 2, 3]
+
+unevaluatedProperties: false
+
+required:
+  - compatible
+  - "#address-cells"
+  - "#size-cells"
+
+additionalProperties: false
-- 
2.25.1



[RESEND 07/14] mfd: mt6370: Add Mediatek MT6370 support

2022-05-31 Thread ChiaEn Wu
From: ChiYuan Huang 

Add Mediatek MT6370 MFD support.

Signed-off-by: ChiYuan Huang 
---
 drivers/mfd/Kconfig  |  13 +++
 drivers/mfd/Makefile |   1 +
 drivers/mfd/mt6370.c | 273 +++
 3 files changed, 287 insertions(+)
 create mode 100644 drivers/mfd/mt6370.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 3b59456f5545..d9a7524a3e0e 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -937,6 +937,19 @@ config MFD_MT6360
  PMIC part includes 2-channel BUCKs and 2-channel LDOs
  LDO part includes 4-channel LDOs
 
+config MFD_MT6370
+   tristate "Mediatek MT6370 SubPMIC"
+   select MFD_CORE
+   select REGMAP_I2C
+   select REGMAP_IRQ
+   depends on I2C
+   help
+ Say Y here to enable MT6370 SubPMIC functional support.
+ It integrate single cell battery charger with adc monitoring, RGB
+ LEDs, dual channel flashlight, WLED backlight driver, display bias
+ voltage supply, one general purpose LDO, and cc logic
+ controller with USBPD commmunication capable.
+
 config MFD_MT6397
tristate "MediaTek MT6397 PMIC Support"
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 858cacf659d6..62b27125420e 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -242,6 +242,7 @@ obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC)  += 
intel_soc_pmic_bxtwc.o
 obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC) += intel_soc_pmic_chtwc.o
 obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI)  += intel_soc_pmic_chtdc_ti.o
 obj-$(CONFIG_MFD_MT6360)   += mt6360-core.o
+obj-$(CONFIG_MFD_MT6370)   += mt6370.o
 mt6397-objs:= mt6397-core.o mt6397-irq.o mt6358-irq.o
 obj-$(CONFIG_MFD_MT6397)   += mt6397.o
 obj-$(CONFIG_INTEL_SOC_PMIC_MRFLD) += intel_soc_pmic_mrfld.o
diff --git a/drivers/mfd/mt6370.c b/drivers/mfd/mt6370.c
new file mode 100644
index ..a5a07be7ccc2
--- /dev/null
+++ b/drivers/mfd/mt6370.c
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+enum {
+   MT6370_USBC_I2C = 0,
+   MT6370_PMU_I2C,
+   MT6370_MAX_I2C
+};
+
+#define MT6370_REG_DEV_INFO0x100
+#define MT6370_REG_CHG_IRQ10x1C0
+#define MT6370_REG_CHG_MASK1   0x1E0
+
+#define MT6370_VENID_MASK  GENMASK(7, 4)
+
+#define MT6370_NUM_IRQREGS 16
+#define MT6370_USBC_I2CADDR0x4E
+#define MT6370_REG_ADDRLEN 2
+#define MT6370_REG_MAXADDR 0x1FF
+
+struct mt6370_info {
+   struct i2c_client *i2c[MT6370_MAX_I2C];
+   struct device *dev;
+   struct regmap *regmap;
+   struct regmap_irq_chip_data *irq_data;
+};
+
+static const struct regmap_irq mt6370_irqs[] = {
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHGON, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TREG, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_AICR, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_MIVR, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_PWR_RDY, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_FL_CHG_VINOVP, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VSYSUV, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VSYSOV, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VBATOV, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VINOVPCHG, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_COLD, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_COOL, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_WARM, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_HOT, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_STATC, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_FAULT, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_STATC, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TMR, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_BATABS, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_ADPBAD, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_RVP, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_TSHUTDOWN, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_IINMEAS, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_ICCMEAS, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHGDET_DONE, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_WDTMR, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_SSFINISH, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_RECHG, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TERM, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_IEOC, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_ADC_DONE, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_PUMPX_DONE, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_BATUV, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_MIDOV, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_OLP, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_ATTACH, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_DETACH, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_STPDONE, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_VBUSDET_DONE, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_DET, 8),
+   REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHGDET

[RESEND 06/14] dt-bindings: mfd: Add Mediatek MT6370 binding

2022-05-31 Thread ChiaEn Wu
From: ChiYuan Huang 

Add Mediatek MT6370 binding documentation.

Signed-off-by: ChiYuan Huang 
---
 .../bindings/mfd/mediatek,mt6370.yaml | 282 ++
 .../dt-bindings/iio/adc/mediatek,mt6370_adc.h |  18 ++
 include/dt-bindings/mfd/mediatek,mt6370.h |  83 ++
 3 files changed, 383 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
 create mode 100644 include/dt-bindings/iio/adc/mediatek,mt6370_adc.h
 create mode 100644 include/dt-bindings/mfd/mediatek,mt6370.h

diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml 
b/Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
new file mode 100644
index ..96a12dce0108
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
@@ -0,0 +1,282 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/mediatek,mt6370.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT6370 SubPMIC
+
+maintainers:
+  - ChiYuan Huang 
+
+description: |
+  MT6370 is a highly-integrated smart power management IC, which includes a
+  single cell Li-Ion/Li-Polymer switching battery charger, a USB Type-C &
+  Power Delivery (PD) controller, dual flash LED current sources, a RGB LED
+  driver, a backlight WLED driver, a display bias driver and a general LDO for
+  portable devices.
+
+properties:
+  compatible:
+const: mediatek,mt6370
+
+  reg:
+maxItems: 1
+
+  wakeup-source: true
+
+  interrupts:
+maxItems: 1
+
+  interrupt-controller: true
+
+  '#interrupt-cells':
+const: 1
+
+  adc:
+type: object
+description: |
+  List the compatible configurations of MT6370 ADC.
+
+properties:
+  compatible:
+const: mediatek,mt6370-adc
+
+  "#io-channel-cells":
+const: 1
+
+required:
+  - compatible
+  - '#io-channel-cells'
+
+  backlight:
+type: object
+$ref: /schemas/leds/backlight/mediatek,mt6370-backlight.yaml#
+
+  charger:
+type: object
+$ref: /schemas/power/supply/mediatek,mt6370-charger.yaml#
+
+  tcpc:
+type: object
+$ref: /schemas/usb/mediatek,mt6370-tcpc.yaml#
+
+  indicator:
+type: object
+$ref: /schemas/leds/mediatek,mt6370-indicator.yaml#
+
+  flashlight:
+type: object
+$ref: /schemas/leds/mediatek,mt6370-flashlight.yaml#
+
+  regulators:
+type: object
+description: |
+  List all supported regulators
+
+patternProperties:
+  "^(dsvbst|vibldo)$":
+$ref: /schemas/regulator/regulator.yaml#
+type: object
+unevaluatedProperties: false
+
+  "^(dsvpos|dsvneg)$":
+$ref: /schemas/regulator/regulator.yaml#
+type: object
+unevaluatedProperties: false
+
+properties:
+  enable-gpio:
+maxItems: 1
+description: |
+  Specify a valid 'enable' gpio for the regulator and it's optional
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - interrupt-controller
+  - '#interrupt-cells'
+  - regulators
+  - adc
+  - backlight
+  - indicator
+  - tcpc
+  - charger
+  - flashlight
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+#include 
+#include 
+#include 
+i2c {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  mt6370@34 {
+compatible = "mediatek,mt6370";
+reg = <0x34>;
+wakeup-source;
+interrupts-extended = <&gpio26 3 IRQ_TYPE_LEVEL_LOW>;
+interrupt-controller;
+#interrupt-cells = <1>;
+
+mt6370_adc: adc {
+  compatible = "mediatek,mt6370-adc";
+  #io-channel-cells = <1>;
+};
+
+backlight {
+  compatible = "mediatek,mt6370-backlight";
+  mediatek,bled-channel-use = /bits/ 8 <15>;
+};
+
+charger {
+  compatible = "mediatek,mt6370-charger";
+  interrupts = , ,
+   ;
+  interrupt-names = "attach_i", "uvp_d_evt", "mivr";
+  io-channels = <&mt6370_adc MT6370_CHAN_IBUS>;
+
+  mt6370_otg_vbus: usb-otg-vbus {
+regulator-compatible = "mt6370,otg-vbus";
+regulator-name = "usb-otg-vbus";
+regulator-min-microvolt = <435>;
+regulator-max-microvolt = <580>;
+regulator-min-microamp = <50>;
+regulator-max-microamp = <300>;
+  };
+};
+
+indicator {
+  compatible = "mediatek,mt6370-indicator";
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  multi-led@0 {
+reg = <0>;
+function = LED_FUNCTION_INDICATOR;
+color = ;
+led-max-microamp = <24000>;
+#address-cells = <1>;
+#size-cells = <0>;
+mediatek,soft-start = <3>;
+  led@0 {
+reg = <0>;
+color = ;
+  };
+  

Re: [PATCH] drm/msm/dpu: Remove unused code

2022-05-31 Thread Abhinav Kumar




On 5/24/2022 1:14 AM, Jiapeng Chong wrote:

Eliminate the follow clang warning:

drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c:544:33: warning: variable
‘mode’ set but not used [-Wunused-but-set-variable].

Reported-by: Abaci Robot 
Signed-off-by: Jiapeng Chong 


Fixes: 3177589c6e93("drm/msm/dpu: encoder: drop unused mode_fixup callback")

Reviewed-by: Abhinav Kumar 


---
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 --
  1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 52516eb20cb8..658171799b9a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -541,7 +541,6 @@ static int dpu_encoder_virt_atomic_check(
struct dpu_encoder_virt *dpu_enc;
struct msm_drm_private *priv;
struct dpu_kms *dpu_kms;
-   const struct drm_display_mode *mode;
struct drm_display_mode *adj_mode;
struct msm_display_topology topology;
struct dpu_global_state *global_state;
@@ -559,7 +558,6 @@ static int dpu_encoder_virt_atomic_check(
  
  	priv = drm_enc->dev->dev_private;

dpu_kms = to_dpu_kms(priv->kms);
-   mode = &crtc_state->mode;
adj_mode = &crtc_state->adjusted_mode;
global_state = dpu_kms_get_global_state(crtc_state->state);
if (IS_ERR(global_state))


[Bug 205089] amdgpu : drm:amdgpu_cs_ioctl : Failed to initialize parser -125

2022-05-31 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=205089

--- Comment #46 from Luke A. Guest (lagu...@archeia.com) ---
Can confirm, for my case, emerge -av @mesa (where @mesa is libdrm, mes and
mesa-tools from git HEAD) fixes it.

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.

Re: [PATCH v3] dma-buf: Add a capabilities directory

2022-05-31 Thread Greg KH
On Tue, May 31, 2022 at 07:53:50AM -0500, Jason Ekstrand wrote:
> On Mon, 2022-05-30 at 10:26 +0200, Greg KH wrote:
> > On Mon, May 30, 2022 at 08:15:04AM +, Simon Ser wrote:
> > > On Monday, May 30th, 2022 at 09:20, Greg KH
> > >  wrote:
> > > 
> > > > > > +static struct attribute *dma_buf_caps_attrs[] = {
> > > > > > +   &dma_buf_sync_file_import_export_attr.attr,
> > > > > > +   NULL,
> > > > > > +};
> > > > > > +
> > > > > > +static const struct attribute_group dma_buf_caps_attr_group
> > > > > > = {
> > > > > > +   .attrs = dma_buf_caps_attrs,
> > > > > > +};
> > > > > 
> > > > > Didn't we had macros for those? I think I have seen something
> > > > > for that.
> > > > 
> > > > Yes, please use ATTRIBUTE_GROUPS()
> > > 
> > > This doesn't allow the user to set a group name, and creates an
> > > unused
> > > "_groups" variable, causing warnings.
> > 
> > Then set a group name.
> > 
> > But you really want to almost always be using lists of groups, which
> > is
> > why that macro works that way.
> 
> I think I see the confusion here.  The ATTRIBUTE_GROUPS() macro is
> intended for device drivers and to be used with add_device().  However,
> this is dma-buf so there is no device and no add_device() call to hook.
> Unless there are other magic macros to use in this case, I think we're
> stuck doing it manually.

Have a list of attribute groups and add it to the kobject when you
create it so they all get created at the same time.

Don't do piece-meal "add one, and then another, and then another" as
that just gets messy and complex and impossible to unwind the error
conditions from.

sysfs_create_groups() is what you need to use here.  I need to drop
sysfs_create_group() one day...

thanks,

greg k-h


Re: [RFC PATCH 1/1] drm/format-helper: Add KUnit tests for drm_fb_xrgb8888_to_rgb332()

2022-05-31 Thread José Expósito
Hi Daniel,

Thanks for looking into the patch and for your comments.

On Mon, May 30, 2022 at 03:57:56PM -0700, Daniel Latypov wrote:
> A few initial notes:
> a) normally, `select`ing other kconfigs is discouraged. It's not
> explicitly called out in
> https://www.kernel.org/doc/html/latest/dev-tools/kunit/style.html#test-kconfig-entries
> but this was the conclusion after  some debate on the mailing lists
> earlier.
>
> b) I see `dst` is allocated with kzalloc but not freed. Should we use
> `kunit_kzalloc()` instead so it does get automatically freed?

Ooops yes, it was in my "I'll handle that once it works" list, but I
forgot to fix it, thanks for pointing it out
 
> > > > ---
> > > >  drivers/gpu/drm/Kconfig  |  12 ++
> > > >  drivers/gpu/drm/Makefile |   3 +
> > > >  drivers/gpu/drm/drm_format_helper_test.c | 166 +++
> > > >  3 files changed, 181 insertions(+)
> > > >  create mode 100644 drivers/gpu/drm/drm_format_helper_test.c
> > > >
> > > > diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> > > > index e88c497fa010..d92be6faef15 100644
> > > > --- a/drivers/gpu/drm/Kconfig
> > > > +++ b/drivers/gpu/drm/Kconfig
> > > > @@ -76,6 +76,18 @@ config DRM_KMS_HELPER
> > > > help
> > > >   CRTC helpers for KMS drivers.
> > > >
> > > > +config DRM_FORMAR_HELPER_TEST
> > > > +   bool "drm_format_helper tests" if !KUNIT_ALL_TESTS
> > > > +   depends on DRM && KUNIT=y
> > > > +   select DRM_KMS_HELPER
> 
> From above, a)
> Specifically here, it'd be encouraged to instead do
>   depends on DRM && KUNIT=y && DRM_KMS_HELPER

My first attempt was to go with:

depends on KUNIT=y && DRM && DRM_KMS_HELPER

However, when I try to run the tests I get this error:

$ ./tools/testing/kunit/kunit.py run --kunitconfig=drivers/gpu/drm 
--arch=x86_64
Regenerating .config ...
Populating config with:
$ make ARCH=x86_64 olddefconfig O=.kunit
ERROR:root:Not all Kconfig options selected in kunitconfig were in the 
generated .config.
This is probably due to unsatisfied dependencies.
Missing: CONFIG_DRM_KMS_HELPER=y, CONFIG_DRM_FORMAR_HELPER_TEST=y

I wasn't able to figure out why that was happening, so I decided to use
"select", which seems to solve the problem.

Do you know why this could be happening?

> Ideally, using a .kunitconfig file would make it so having to select
> DRM_KMS_HELPER manually isn't that annoying.
> 
> > > AFAIK, kunit test cases are supposed to have a .kunitconfig too to
> > > enable the kunit tests easily.
> > >
> > > Maxime
> >
> > A .kuniconfig example is present in the cover letter. My understanding
> > from the docs:
> >
> > https://docs.kernel.org/dev-tools/kunit/run_wrapper.html#create-a-kunitconfig-file
> 
> The bit of the documentation you're looking for is
> https://www.kernel.org/doc/html/latest/dev-tools/kunit/running_tips.html#defining-a-set-of-tests
> You can create a drivers/gpu/drm/.kunitconfig file and run with
> $ ./tools/testing/kunit/kunit.py run --kunitconfig=drivers/gpu/drm 
> --arch=x86_86
> 
> The contents of that file would be just like
>   CONFIG_KUNIT=y
>   CONFIG_DRM=y
>   CONFIG_DRM_KMS_HELPER=y  # if no `select`
>   CONFIG_DRM_FORMAR_HELPER_TEST=y

Noted, thanks a lot, I'll include it in the final version of the patch.

By the way, I also included it in an unrelated patch, just in case you
are wondering why I emailed you a random patch:
https://lore.kernel.org/linux-input/20220531181246.190729-1-jose.exposit...@gmail.com/T/

Thanks a lot for your help,
José Expósito

> Re "kunit test cases are supposed to have a .kunitconfig too"
> As I noted in the docs:
>   This is a relatively new feature (5.12+) so we don’t have any
> conventions yet about on what files should be checked in versus just
> kept around locally. It’s up to you and your maintainer to decide if a
> config is useful enough to submit (and therefore have to maintain).
> 
> So it's up to whatever people think works best/is worth it.
> I think in this case, it makes sense to add the file.
> 
> > Is that, like the .config file, the .kunitconfig file is not meant to
> > be included in git, but I'm sure someone else will clarify this point.
> 
> That bit of the docs needs to be rewritten.
> You're recommended to check in a drivers/gpu/drm/.kunitconfig file into git.
> 
> Context: `kunit.py` used to use the "/.kunitconfig" file.
> Anytime you wanted to run more tests, you'd append to that file.
> So we agreed that no one should check in that file specifically.
> 
> Now kunit.py
> * uses "/.kunitconfig", by default: ".kunit/.kunitconfig"
> * has the --kunitconfig flag so you can use different files
> so it's no longer as relevant.
> 
> Hope that helps,
> Daniel


Re: [PATCH] drm/nouveau/fifo/gv100-: set gv100_fifo_runlist storage-class to static

2022-05-31 Thread Lyude Paul
Reviewed-by: Lyude Paul 

Will push to the appropriate branch in a moment

On Sat, 2022-05-28 at 10:18 -0400, Tom Rix wrote:
> sparse reports
> drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c:56:1: warning: symbol
> 'gv100_fifo_runlist' was not declared. Should it be static?
> 
> gv100_fifo_runlist is only used in gv100.c, so change it to static.
> 
> Signed-off-by: Tom Rix 
> ---
>  drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c
> b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c
> index 70e16a91ac12..faf0fe9f704c 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c
> @@ -52,7 +52,7 @@ gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp,
> nvkm_wo32(memory, offset + 0xc, 0x);
>  }
>  
> -const struct gk104_fifo_runlist_func
> +static const struct gk104_fifo_runlist_func
>  gv100_fifo_runlist = {
> .size = 16,
> .cgrp = gv100_fifo_runlist_cgrp,

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH v4 07/13] lib: test_hmm add ioctl to get zone device type

2022-05-31 Thread Sierra Guiza, Alejandro (Alex)



On 5/31/2022 12:31 PM, Andrew Morton wrote:

On Tue, 31 May 2022 10:56:23 -0500 Alex Sierra  wrote:


new ioctl cmd added to query zone device type. This will be
used once the test_hmm adds zone device coherent type.

@@ -1026,6 +1027,15 @@ static int dmirror_snapshot(struct dmirror *dmirror,
return ret;
  }
  
+static int dmirror_get_device_type(struct dmirror *dmirror,

+   struct hmm_dmirror_cmd *cmd)
+{
+   mutex_lock(&dmirror->mutex);
+   cmd->zone_device_type = dmirror->mdevice->zone_device_type;
+   mutex_unlock(&dmirror->mutex);

What does the locking here do?

Presumably cmd->zone_device_type can become out of date the instant the
mutex is released, so what was the point in taking the mutex?


Actually this is not used at all. Thanks for finding it. Honestly, I 
don't remember what we used this type request for.

I will remove all related code  and send a new patch series version.

Regards,
Alex Sierra


And does it make sense to return potentially out-of-date info to
userspace?  Perhaps this interface simply shouldn't exist?


[Bug 213145] AMDGPU resets, timesout and crashes after "*ERROR* Waiting for fences timed out!"

2022-05-31 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=213145

--- Comment #18 from Eric Wheeler (bugzilla-ker...@z.ewheeler.org) ---
Nix, did you try Linux 5.18?  It worked for me...

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.

Re: [PATCH 1/2] drm/meson: encoder_cvbs: Fix refcount leak in meson_encoder_cvbs_init

2022-05-31 Thread Martin Blumenstingl
On Tue, May 31, 2022 at 4:49 PM Miaoqian Lin  wrote:
>
> of_graph_get_remote_node() returns remote device nodepointer with
> refcount incremented, we should use of_node_put() on it when done.
> Add missing of_node_put() to avoid refcount leak.
>
> Fixes: 318ba02cd8a8 ("drm/meson: encoder_cvbs: switch to bridge with 
> ATTACH_NO_CONNECTOR")
> Signed-off-by: Miaoqian Lin 
Reviewed-by: Martin Blumenstingl 


[PATCH v5 00/13] Add MEMORY_DEVICE_COHERENT for coherent device memory mapping

2022-05-31 Thread Alex Sierra
This is our MEMORY_DEVICE_COHERENT patch series rebased and updated
for current 5.18.0

Changes since the last version:
- Fixed problems with migration during long-term pinning in
get_user_pages
- Open coded vm_normal_lru_pages as suggested in previous code review
- Update hmm_gup_test with more get_user_pages calls, include
hmm_cow_in_device in hmm-test.

This patch series introduces MEMORY_DEVICE_COHERENT, a type of memory
owned by a device that can be mapped into CPU page tables like
MEMORY_DEVICE_GENERIC and can also be migrated like
MEMORY_DEVICE_PRIVATE.

This patch series is mostly self-contained except for a few places where
it needs to update other subsystems to handle the new memory type.

System stability and performance are not affected according to our
ongoing testing, including xfstests.

How it works: The system BIOS advertises the GPU device memory
(aka VRAM) as SPM (special purpose memory) in the UEFI system address
map.

The amdgpu driver registers the memory with devmap as
MEMORY_DEVICE_COHERENT using devm_memremap_pages. The initial user for
this hardware page migration capability is the Frontier supercomputer
project. This functionality is not AMD-specific. We expect other GPU
vendors to find this functionality useful, and possibly other hardware
types in the future.

Our test nodes in the lab are similar to the Frontier configuration,
with .5 TB of system memory plus 256 GB of device memory split across
4 GPUs, all in a single coherent address space. Page migration is
expected to improve application efficiency significantly. We will
report empirical results as they become available.

Coherent device type pages at gup are now migrated back to system
memory if they are being pinned long-term (FOLL_LONGTERM). The reason
is, that long-term pinning would interfere with the device memory
manager owning the device-coherent pages (e.g. evictions in TTM).
These series incorporate Alistair Popple patches to do this
migration from pin_user_pages() calls. hmm_gup_test has been added to
hmm-test to test different get user pages calls.

This series includes handling of device-managed anonymous pages
returned by vm_normal_pages. Although they behave like normal pages
for purposes of mapping in CPU page tables and for COW, they do not
support LRU lists, NUMA migration or THP.

We also introduced a FOLL_LRU flag that adds the same behaviour to
follow_page and related APIs, to allow callers to specify that they
expect to put pages on an LRU list.

v2:
- Rebase to latest 5.18-rc7.
- Drop patch "mm: add device coherent checker to remove migration pte"
and modify try_to_migrate_one, to let DEVICE_COHERENT pages fall
through to normal page path. Based on Alistair Popple's comment.
- Fix comment formatting.
- Reword comment in vm_normal_page about pte_devmap().
- Merge "drm/amdkfd: coherent type as sys mem on migration to ram" to
"drm/amdkfd: add SPM support for SVM".

v3:
- Rebase to latest 5.18.0.
- Patch "mm: handling Non-LRU pages returned by vm_normal_pages"
reordered.
- Add WARN_ON_ONCE for thp device coherent case.

v4:
- Rebase to latest 5.18.0
- Fix consitency between pages with FOLL_LRU flag set and pte_devmap
at follow_page_pte.

v5:
- Remove unused zone_device_type from lib/test_hmm and
selftest/vm/hmm-test.c.

Alex Sierra (11):
  mm: add zone device coherent type memory support
  mm: handling Non-LRU pages returned by vm_normal_pages
  mm: add device coherent vma selection for memory migration
  drm/amdkfd: add SPM support for SVM
  lib: test_hmm add ioctl to get zone device type
  lib: test_hmm add module param for zone device type
  lib: add support for device coherent type in test_hmm
  tools: update hmm-test to support device coherent type
  tools: update test_hmm script to support SP config
  tools: add hmm gup tests for device coherent type
  tools: add selftests to hmm for COW in device memory

Alistair Popple (2):
  mm: remove the vma check in migrate_vma_setup()
  mm/gup: migrate device coherent pages when pinning instead of failing

 drivers/gpu/drm/amd/amdkfd/kfd_migrate.c |  34 ++-
 fs/proc/task_mmu.c   |   2 +-
 include/linux/memremap.h |  19 ++
 include/linux/migrate.h  |   1 +
 include/linux/mm.h   |   3 +-
 lib/test_hmm.c   | 337 +--
 lib/test_hmm_uapi.h  |  19 +-
 mm/gup.c |  53 +++-
 mm/huge_memory.c |   2 +-
 mm/internal.h|   1 +
 mm/khugepaged.c  |   9 +-
 mm/ksm.c |   6 +-
 mm/madvise.c |   4 +-
 mm/memcontrol.c  |   7 +-
 mm/memory-failure.c  |   8 +-
 mm/memory.c  |   9 +-
 mm/mempolicy.c   |   2 +-
 mm/memremap.c|  10 +
 mm/migrate.c  

[PATCH v5 01/13] mm: add zone device coherent type memory support

2022-05-31 Thread Alex Sierra
Device memory that is cache coherent from device and CPU point of view.
This is used on platforms that have an advanced system bus (like CAPI
or CXL). Any page of a process can be migrated to such memory. However,
no one should be allowed to pin such memory so that it can always be
evicted.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
Reviewed-by: Alistair Popple 
[hch: rebased ontop of the refcount changes,
  removed is_dev_private_or_coherent_page]
Signed-off-by: Christoph Hellwig 
---
 include/linux/memremap.h | 19 +++
 mm/memcontrol.c  |  7 ---
 mm/memory-failure.c  |  8 ++--
 mm/memremap.c| 10 ++
 mm/migrate_device.c  | 16 +++-
 mm/rmap.c|  5 +++--
 6 files changed, 49 insertions(+), 16 deletions(-)

diff --git a/include/linux/memremap.h b/include/linux/memremap.h
index 8af304f6b504..9f752ebed613 100644
--- a/include/linux/memremap.h
+++ b/include/linux/memremap.h
@@ -41,6 +41,13 @@ struct vmem_altmap {
  * A more complete discussion of unaddressable memory may be found in
  * include/linux/hmm.h and Documentation/vm/hmm.rst.
  *
+ * MEMORY_DEVICE_COHERENT:
+ * Device memory that is cache coherent from device and CPU point of view. This
+ * is used on platforms that have an advanced system bus (like CAPI or CXL). A
+ * driver can hotplug the device memory using ZONE_DEVICE and with that memory
+ * type. Any page of a process can be migrated to such memory. However no one
+ * should be allowed to pin such memory so that it can always be evicted.
+ *
  * MEMORY_DEVICE_FS_DAX:
  * Host memory that has similar access semantics as System RAM i.e. DMA
  * coherent and supports page pinning. In support of coordinating page
@@ -61,6 +68,7 @@ struct vmem_altmap {
 enum memory_type {
/* 0 is reserved to catch uninitialized type fields */
MEMORY_DEVICE_PRIVATE = 1,
+   MEMORY_DEVICE_COHERENT,
MEMORY_DEVICE_FS_DAX,
MEMORY_DEVICE_GENERIC,
MEMORY_DEVICE_PCI_P2PDMA,
@@ -143,6 +151,17 @@ static inline bool folio_is_device_private(const struct 
folio *folio)
return is_device_private_page(&folio->page);
 }
 
+static inline bool is_device_coherent_page(const struct page *page)
+{
+   return is_zone_device_page(page) &&
+   page->pgmap->type == MEMORY_DEVICE_COHERENT;
+}
+
+static inline bool folio_is_device_coherent(const struct folio *folio)
+{
+   return is_device_coherent_page(&folio->page);
+}
+
 static inline bool is_pci_p2pdma_page(const struct page *page)
 {
return IS_ENABLED(CONFIG_PCI_P2PDMA) &&
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index abec50f31fe6..93f80d7ca148 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -5665,8 +5665,8 @@ static int mem_cgroup_move_account(struct page *page,
  *   2(MC_TARGET_SWAP): if the swap entry corresponding to this pte is a
  * target for charge migration. if @target is not NULL, the entry is stored
  * in target->ent.
- *   3(MC_TARGET_DEVICE): like MC_TARGET_PAGE  but page is 
MEMORY_DEVICE_PRIVATE
- * (so ZONE_DEVICE page and thus not on the lru).
+ *   3(MC_TARGET_DEVICE): like MC_TARGET_PAGE  but page is device memory and
+ *   thus not on the lru.
  * For now we such page is charge like a regular page would be as for all
  * intent and purposes it is just special memory taking the place of a
  * regular page.
@@ -5704,7 +5704,8 @@ static enum mc_target_type get_mctgt_type(struct 
vm_area_struct *vma,
 */
if (page_memcg(page) == mc.from) {
ret = MC_TARGET_PAGE;
-   if (is_device_private_page(page))
+   if (is_device_private_page(page) ||
+   is_device_coherent_page(page))
ret = MC_TARGET_DEVICE;
if (target)
target->page = page;
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index b85661cbdc4a..0b6a0a01ee09 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1683,12 +1683,16 @@ static int memory_failure_dev_pagemap(unsigned long 
pfn, int flags,
goto unlock;
}
 
-   if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
+   switch (pgmap->type) {
+   case MEMORY_DEVICE_PRIVATE:
+   case MEMORY_DEVICE_COHERENT:
/*
-* TODO: Handle HMM pages which may need coordination
+* TODO: Handle device pages which may need coordination
 * with device-side memory.
 */
goto unlock;
+   default:
+   break;
}
 
/*
diff --git a/mm/memremap.c b/mm/memremap.c
index 2b92e97cb25b..dbd2631b3520 100644
--- a/mm/memremap.c
+++ b/mm/memremap.c
@@ -315,6 +315,16 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
return ERR_PTR(-EINVAL);
}
break;

[PATCH v5 02/13] mm: handling Non-LRU pages returned by vm_normal_pages

2022-05-31 Thread Alex Sierra
With DEVICE_COHERENT, we'll soon have vm_normal_pages() return
device-managed anonymous pages that are not LRU pages. Although they
behave like normal pages for purposes of mapping in CPU page, and for
COW. They do not support LRU lists, NUMA migration or THP.

We also introduced a FOLL_LRU flag that adds the same behaviour to
follow_page and related APIs, to allow callers to specify that they
expect to put pages on an LRU list.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
---
 fs/proc/task_mmu.c | 2 +-
 include/linux/mm.h | 3 ++-
 mm/gup.c   | 6 +-
 mm/huge_memory.c   | 2 +-
 mm/khugepaged.c| 9 ++---
 mm/ksm.c   | 6 +++---
 mm/madvise.c   | 4 ++--
 mm/memory.c| 9 -
 mm/mempolicy.c | 2 +-
 mm/migrate.c   | 4 ++--
 mm/mlock.c | 2 +-
 mm/mprotect.c  | 2 +-
 12 files changed, 33 insertions(+), 18 deletions(-)

diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 2d04e3470d4c..2dd8c8a66924 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1792,7 +1792,7 @@ static struct page *can_gather_numa_stats(pte_t pte, 
struct vm_area_struct *vma,
return NULL;
 
page = vm_normal_page(vma, addr, pte);
-   if (!page)
+   if (!page || is_zone_device_page(page))
return NULL;
 
if (PageReserved(page))
diff --git a/include/linux/mm.h b/include/linux/mm.h
index bc8f326be0ce..d3f43908ff8d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -601,7 +601,7 @@ struct vm_operations_struct {
 #endif
/*
 * Called by vm_normal_page() for special PTEs to find the
-* page for @addr.  This is useful if the default behavior
+* page for @addr. This is useful if the default behavior
 * (using pte_page()) would not find the correct page.
 */
struct page *(*find_special_page)(struct vm_area_struct *vma,
@@ -2934,6 +2934,7 @@ struct page *follow_page(struct vm_area_struct *vma, 
unsigned long address,
 #define FOLL_NUMA  0x200   /* force NUMA hinting page fault */
 #define FOLL_MIGRATION 0x400   /* wait for page to replace migration entry */
 #define FOLL_TRIED 0x800   /* a retry, previous pass started an IO */
+#define FOLL_LRU0x1000  /* return only LRU (anon or page cache) */
 #define FOLL_REMOTE0x2000  /* we are working on non-current tsk/mm */
 #define FOLL_COW   0x4000  /* internal GUP flag */
 #define FOLL_ANON  0x8000  /* don't do file mappings */
diff --git a/mm/gup.c b/mm/gup.c
index 551264407624..48b45bcc8501 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -532,7 +532,11 @@ static struct page *follow_page_pte(struct vm_area_struct 
*vma,
}
 
page = vm_normal_page(vma, address, pte);
-   if (!page && pte_devmap(pte) && (flags & (FOLL_GET | FOLL_PIN))) {
+   if ((flags & FOLL_LRU) && ((page && is_zone_device_page(page)) ||
+   (!page && pte_devmap(pte {
+   page = ERR_PTR(-EEXIST);
+   goto out;
+   } else if (!page && pte_devmap(pte) && (flags & (FOLL_GET | FOLL_PIN))) 
{
/*
 * Only return device mapping pages in the FOLL_GET or FOLL_PIN
 * case since they are only valid while holding the pgmap
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index a77c78a2b6b5..48182c8fe151 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2906,7 +2906,7 @@ static int split_huge_pages_pid(int pid, unsigned long 
vaddr_start,
}
 
/* FOLL_DUMP to ignore special (like zero) pages */
-   page = follow_page(vma, addr, FOLL_GET | FOLL_DUMP);
+   page = follow_page(vma, addr, FOLL_GET | FOLL_DUMP | FOLL_LRU);
 
if (IS_ERR(page))
continue;
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 16be62d493cd..671ac7800e53 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -618,7 +618,7 @@ static int __collapse_huge_page_isolate(struct 
vm_area_struct *vma,
goto out;
}
page = vm_normal_page(vma, address, pteval);
-   if (unlikely(!page)) {
+   if (unlikely(!page) || unlikely(is_zone_device_page(page))) {
result = SCAN_PAGE_NULL;
goto out;
}
@@ -1267,7 +1267,7 @@ static int khugepaged_scan_pmd(struct mm_struct *mm,
writable = true;
 
page = vm_normal_page(vma, _address, pteval);
-   if (unlikely(!page)) {
+   if (unlikely(!page) || unlikely(is_zone_device_page(page))) {
result = SCAN_PAGE_NULL;
goto out_unmap;
}
@@ -1479,7 +1479,8 @@ void collapse_pte_mapped_thp(struct mm_struct *mm, 
unsigned long addr)
goto abort;
 
page = vm_normal_page(vma, addr, *pte);
-
+   if (WARN_ON_ONCE(page && is_zone_device_p

[PATCH v5 04/13] mm: remove the vma check in migrate_vma_setup()

2022-05-31 Thread Alex Sierra
From: Alistair Popple 

migrate_vma_setup() checks that a valid vma is passed so that the page
tables can be walked to find the pfns associated with a given address
range. However in some cases the pfns are already known, such as when
migrating device coherent pages during pin_user_pages() meaning a valid
vma isn't required.

Signed-off-by: Alistair Popple 
Acked-by: Felix Kuehling 
Signed-off-by: Christoph Hellwig 
---
 mm/migrate_device.c | 34 +-
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/mm/migrate_device.c b/mm/migrate_device.c
index 18bc6483f63a..cf9668376c5a 100644
--- a/mm/migrate_device.c
+++ b/mm/migrate_device.c
@@ -486,24 +486,24 @@ int migrate_vma_setup(struct migrate_vma *args)
 
args->start &= PAGE_MASK;
args->end &= PAGE_MASK;
-   if (!args->vma || is_vm_hugetlb_page(args->vma) ||
-   (args->vma->vm_flags & VM_SPECIAL) || vma_is_dax(args->vma))
-   return -EINVAL;
-   if (nr_pages <= 0)
-   return -EINVAL;
-   if (args->start < args->vma->vm_start ||
-   args->start >= args->vma->vm_end)
-   return -EINVAL;
-   if (args->end <= args->vma->vm_start || args->end > args->vma->vm_end)
-   return -EINVAL;
if (!args->src || !args->dst)
return -EINVAL;
-
-   memset(args->src, 0, sizeof(*args->src) * nr_pages);
-   args->cpages = 0;
-   args->npages = 0;
-
-   migrate_vma_collect(args);
+   if (args->vma) {
+   if (is_vm_hugetlb_page(args->vma) ||
+   (args->vma->vm_flags & VM_SPECIAL) || vma_is_dax(args->vma))
+   return -EINVAL;
+   if (args->start < args->vma->vm_start ||
+   args->start >= args->vma->vm_end)
+   return -EINVAL;
+   if (args->end <= args->vma->vm_start ||
+   args->end > args->vma->vm_end)
+   return -EINVAL;
+   memset(args->src, 0, sizeof(*args->src) * nr_pages);
+   args->cpages = 0;
+   args->npages = 0;
+
+   migrate_vma_collect(args);
+   }
 
if (args->cpages)
migrate_vma_unmap(args);
@@ -685,7 +685,7 @@ void migrate_vma_pages(struct migrate_vma *migrate)
continue;
}
 
-   if (!page) {
+   if (!page && migrate->vma) {
if (!(migrate->src[i] & MIGRATE_PFN_MIGRATE))
continue;
if (!notified) {
-- 
2.32.0



[PATCH v5 05/13] mm/gup: migrate device coherent pages when pinning instead of failing

2022-05-31 Thread Alex Sierra
From: Alistair Popple 

Currently any attempts to pin a device coherent page will fail. This is
because device coherent pages need to be managed by a device driver, and
pinning them would prevent a driver from migrating them off the device.

However this is no reason to fail pinning of these pages. These are
coherent and accessible from the CPU so can be migrated just like
pinning ZONE_MOVABLE pages. So instead of failing all attempts to pin
them first try migrating them out of ZONE_DEVICE.

Signed-off-by: Alistair Popple 
Acked-by: Felix Kuehling 
[hch: rebased to the split device memory checks,
  moved migrate_device_page to migrate_device.c]
Signed-off-by: Christoph Hellwig 
---
 mm/gup.c| 47 +++-
 mm/internal.h   |  1 +
 mm/migrate_device.c | 53 +
 3 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/mm/gup.c b/mm/gup.c
index 48b45bcc8501..e6093c31f932 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1895,9 +1895,43 @@ static long check_and_migrate_movable_pages(unsigned 
long nr_pages,
continue;
prev_folio = folio;
 
-   if (folio_is_pinnable(folio))
+   /*
+* Device private pages will get faulted in during gup so it
+* shouldn't be possible to see one here.
+*/
+   if (WARN_ON_ONCE(folio_is_device_private(folio))) {
+   ret = -EFAULT;
+   goto unpin_pages;
+   }
+
+   /*
+* Device coherent pages are managed by a driver and should not
+* be pinned indefinitely as it prevents the driver moving the
+* page. So when trying to pin with FOLL_LONGTERM instead try
+* to migrate the page out of device memory.
+*/
+   if (folio_is_device_coherent(folio)) {
+   WARN_ON_ONCE(PageCompound(&folio->page));
+
+   /*
+* Migration will fail if the page is pinned, so convert
+* the pin on the source page to a normal reference.
+*/
+   if (gup_flags & FOLL_PIN) {
+   get_page(&folio->page);
+   unpin_user_page(&folio->page);
+   }
+
+   pages[i] = migrate_device_page(&folio->page, gup_flags);
+   if (!pages[i]) {
+   ret = -EBUSY;
+   goto unpin_pages;
+   }
continue;
+   }
 
+   if (folio_is_pinnable(folio))
+   continue;
/*
 * Try to move out any movable page before pinning the range.
 */
@@ -1933,10 +1967,13 @@ static long check_and_migrate_movable_pages(unsigned 
long nr_pages,
return nr_pages;
 
 unpin_pages:
-   if (gup_flags & FOLL_PIN) {
-   unpin_user_pages(pages, nr_pages);
-   } else {
-   for (i = 0; i < nr_pages; i++)
+   for (i = 0; i < nr_pages; i++) {
+   if (!pages[i])
+   continue;
+
+   if (gup_flags & FOLL_PIN)
+   unpin_user_page(pages[i]);
+   else
put_page(pages[i]);
}
 
diff --git a/mm/internal.h b/mm/internal.h
index c0f8fbe0445b..eeab4ee7a4a3 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -853,6 +853,7 @@ int numa_migrate_prep(struct page *page, struct 
vm_area_struct *vma,
  unsigned long addr, int page_nid, int *flags);
 
 void free_zone_device_page(struct page *page);
+struct page *migrate_device_page(struct page *page, unsigned int gup_flags);
 
 /*
  * mm/gup.c
diff --git a/mm/migrate_device.c b/mm/migrate_device.c
index cf9668376c5a..5decd26dd551 100644
--- a/mm/migrate_device.c
+++ b/mm/migrate_device.c
@@ -794,3 +794,56 @@ void migrate_vma_finalize(struct migrate_vma *migrate)
}
 }
 EXPORT_SYMBOL(migrate_vma_finalize);
+
+/*
+ * Migrate a device coherent page back to normal memory.  The caller should 
have
+ * a reference on page which will be copied to the new page if migration is
+ * successful or dropped on failure.
+ */
+struct page *migrate_device_page(struct page *page, unsigned int gup_flags)
+{
+   unsigned long src_pfn, dst_pfn = 0;
+   struct migrate_vma args;
+   struct page *dpage;
+
+   lock_page(page);
+   src_pfn = migrate_pfn(page_to_pfn(page)) | MIGRATE_PFN_MIGRATE;
+   args.src = &src_pfn;
+   args.dst = &dst_pfn;
+   args.cpages = 1;
+   args.npages = 1;
+   args.vma = NULL;
+   migrate_vma_setup(&args);
+   if (!(src_pfn & MIGRATE_PFN_MIGRATE))
+   return NULL;
+
+   dpage = alloc_pages(GFP_USER | __GFP_NOWARN, 0);
+

[PATCH v5 03/13] mm: add device coherent vma selection for memory migration

2022-05-31 Thread Alex Sierra
This case is used to migrate pages from device memory, back to system
memory. Device coherent type memory is cache coherent from device and CPU
point of view.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
Reviewed-by: Alistair Poppple 
Signed-off-by: Christoph Hellwig 
---
 include/linux/migrate.h |  1 +
 mm/migrate_device.c | 12 +---
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index 069a89e847f3..b84908debe5c 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -148,6 +148,7 @@ static inline unsigned long migrate_pfn(unsigned long pfn)
 enum migrate_vma_direction {
MIGRATE_VMA_SELECT_SYSTEM = 1 << 0,
MIGRATE_VMA_SELECT_DEVICE_PRIVATE = 1 << 1,
+   MIGRATE_VMA_SELECT_DEVICE_COHERENT = 1 << 2,
 };
 
 struct migrate_vma {
diff --git a/mm/migrate_device.c b/mm/migrate_device.c
index a4847ad65da3..18bc6483f63a 100644
--- a/mm/migrate_device.c
+++ b/mm/migrate_device.c
@@ -148,15 +148,21 @@ static int migrate_vma_collect_pmd(pmd_t *pmdp,
if (is_writable_device_private_entry(entry))
mpfn |= MIGRATE_PFN_WRITE;
} else {
-   if (!(migrate->flags & MIGRATE_VMA_SELECT_SYSTEM))
-   goto next;
pfn = pte_pfn(pte);
-   if (is_zero_pfn(pfn)) {
+   if (is_zero_pfn(pfn) &&
+   (migrate->flags & MIGRATE_VMA_SELECT_SYSTEM)) {
mpfn = MIGRATE_PFN_MIGRATE;
migrate->cpages++;
goto next;
}
page = vm_normal_page(migrate->vma, addr, pte);
+   if (page && !is_zone_device_page(page) &&
+   !(migrate->flags & MIGRATE_VMA_SELECT_SYSTEM))
+   goto next;
+   else if (page && is_device_coherent_page(page) &&
+   (!(migrate->flags & 
MIGRATE_VMA_SELECT_DEVICE_COHERENT) ||
+page->pgmap->owner != migrate->pgmap_owner))
+   goto next;
mpfn = migrate_pfn(pfn) | MIGRATE_PFN_MIGRATE;
mpfn |= pte_write(pte) ? MIGRATE_PFN_WRITE : 0;
}
-- 
2.32.0



[PATCH v5 06/13] drm/amdkfd: add SPM support for SVM

2022-05-31 Thread Alex Sierra
When CPU is connected throug XGMI, it has coherent
access to VRAM resource. In this case that resource
is taken from a table in the device gmc aperture base.
This resource is used along with the device type, which could
be DEVICE_PRIVATE or DEVICE_COHERENT to create the device
page map region.
Also, MIGRATE_VMA_SELECT_DEVICE_COHERENT flag is selected for
coherent type case during migration to device.

Signed-off-by: Alex Sierra 
Reviewed-by: Felix Kuehling 
Signed-off-by: Christoph Hellwig 
---
 drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 34 +++-
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 997650d597ec..39b8c4710caf 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -671,13 +671,15 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct 
svm_range *prange,
migrate.vma = vma;
migrate.start = start;
migrate.end = end;
-   migrate.flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
migrate.pgmap_owner = SVM_ADEV_PGMAP_OWNER(adev);
+   if (adev->gmc.xgmi.connected_to_cpu)
+   migrate.flags = MIGRATE_VMA_SELECT_DEVICE_COHERENT;
+   else
+   migrate.flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
 
buf = kvcalloc(npages,
   2 * sizeof(*migrate.src) + sizeof(uint64_t) + 
sizeof(dma_addr_t),
   GFP_KERNEL);
-
if (!buf)
goto out;
 
@@ -947,7 +949,7 @@ int svm_migrate_init(struct amdgpu_device *adev)
 {
struct kfd_dev *kfddev = adev->kfd.dev;
struct dev_pagemap *pgmap;
-   struct resource *res;
+   struct resource *res = NULL;
unsigned long size;
void *r;
 
@@ -962,28 +964,34 @@ int svm_migrate_init(struct amdgpu_device *adev)
 * should remove reserved size
 */
size = ALIGN(adev->gmc.real_vram_size, 2ULL << 20);
-   res = devm_request_free_mem_region(adev->dev, &iomem_resource, size);
-   if (IS_ERR(res))
-   return -ENOMEM;
+   if (adev->gmc.xgmi.connected_to_cpu) {
+   pgmap->range.start = adev->gmc.aper_base;
+   pgmap->range.end = adev->gmc.aper_base + adev->gmc.aper_size - 
1;
+   pgmap->type = MEMORY_DEVICE_COHERENT;
+   } else {
+   res = devm_request_free_mem_region(adev->dev, &iomem_resource, 
size);
+   if (IS_ERR(res))
+   return -ENOMEM;
+   pgmap->range.start = res->start;
+   pgmap->range.end = res->end;
+   pgmap->type = MEMORY_DEVICE_PRIVATE;
+   }
 
-   pgmap->type = MEMORY_DEVICE_PRIVATE;
pgmap->nr_range = 1;
-   pgmap->range.start = res->start;
-   pgmap->range.end = res->end;
pgmap->ops = &svm_migrate_pgmap_ops;
pgmap->owner = SVM_ADEV_PGMAP_OWNER(adev);
-   pgmap->flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
-
+   pgmap->flags = 0;
/* Device manager releases device-specific resources, memory region and
 * pgmap when driver disconnects from device.
 */
r = devm_memremap_pages(adev->dev, pgmap);
if (IS_ERR(r)) {
pr_err("failed to register HMM device memory\n");
-
/* Disable SVM support capability */
pgmap->type = 0;
-   devm_release_mem_region(adev->dev, res->start, 
resource_size(res));
+   if (pgmap->type == MEMORY_DEVICE_PRIVATE)
+   devm_release_mem_region(adev->dev, res->start,
+   res->end - res->start + 1);
return PTR_ERR(r);
}
 
-- 
2.32.0



[PATCH v5 08/13] lib: test_hmm add module param for zone device type

2022-05-31 Thread Alex Sierra
In order to configure device coherent in test_hmm, two module parameters
should be passed, which correspond to the SP start address of each
device (2) spm_addr_dev0 & spm_addr_dev1. If no parameters are passed,
private device type is configured.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
Reviewed-by: Alistair Poppple 
Signed-off-by: Christoph Hellwig 
---
 lib/test_hmm.c  | 73 -
 lib/test_hmm_uapi.h |  1 +
 2 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/lib/test_hmm.c b/lib/test_hmm.c
index 915ef6b5b0d4..afb30af9f3ff 100644
--- a/lib/test_hmm.c
+++ b/lib/test_hmm.c
@@ -37,6 +37,16 @@
 #define DEVMEM_CHUNK_SIZE  (256 * 1024 * 1024U)
 #define DEVMEM_CHUNKS_RESERVE  16
 
+static unsigned long spm_addr_dev0;
+module_param(spm_addr_dev0, long, 0644);
+MODULE_PARM_DESC(spm_addr_dev0,
+   "Specify start address for SPM (special purpose memory) used 
for device 0. By setting this Coherent device type will be used. Make sure 
spm_addr_dev1 is set too. Minimum SPM size should be DEVMEM_CHUNK_SIZE.");
+
+static unsigned long spm_addr_dev1;
+module_param(spm_addr_dev1, long, 0644);
+MODULE_PARM_DESC(spm_addr_dev1,
+   "Specify start address for SPM (special purpose memory) used 
for device 1. By setting this Coherent device type will be used. Make sure 
spm_addr_dev0 is set too. Minimum SPM size should be DEVMEM_CHUNK_SIZE.");
+
 static const struct dev_pagemap_ops dmirror_devmem_ops;
 static const struct mmu_interval_notifier_ops dmirror_min_ops;
 static dev_t dmirror_dev;
@@ -455,28 +465,44 @@ static int dmirror_write(struct dmirror *dmirror, struct 
hmm_dmirror_cmd *cmd)
return ret;
 }
 
-static bool dmirror_allocate_chunk(struct dmirror_device *mdevice,
+static int dmirror_allocate_chunk(struct dmirror_device *mdevice,
   struct page **ppage)
 {
struct dmirror_chunk *devmem;
-   struct resource *res;
+   struct resource *res = NULL;
unsigned long pfn;
unsigned long pfn_first;
unsigned long pfn_last;
void *ptr;
+   int ret = -ENOMEM;
 
devmem = kzalloc(sizeof(*devmem), GFP_KERNEL);
if (!devmem)
-   return false;
+   return ret;
 
-   res = request_free_mem_region(&iomem_resource, DEVMEM_CHUNK_SIZE,
- "hmm_dmirror");
-   if (IS_ERR(res))
+   switch (mdevice->zone_device_type) {
+   case HMM_DMIRROR_MEMORY_DEVICE_PRIVATE:
+   res = request_free_mem_region(&iomem_resource, 
DEVMEM_CHUNK_SIZE,
+ "hmm_dmirror");
+   if (IS_ERR_OR_NULL(res))
+   goto err_devmem;
+   devmem->pagemap.range.start = res->start;
+   devmem->pagemap.range.end = res->end;
+   devmem->pagemap.type = MEMORY_DEVICE_PRIVATE;
+   break;
+   case HMM_DMIRROR_MEMORY_DEVICE_COHERENT:
+   devmem->pagemap.range.start = (MINOR(mdevice->cdevice.dev) - 2) 
?
+   spm_addr_dev0 :
+   spm_addr_dev1;
+   devmem->pagemap.range.end = devmem->pagemap.range.start +
+   DEVMEM_CHUNK_SIZE - 1;
+   devmem->pagemap.type = MEMORY_DEVICE_COHERENT;
+   break;
+   default:
+   ret = -EINVAL;
goto err_devmem;
+   }
 
-   devmem->pagemap.type = MEMORY_DEVICE_PRIVATE;
-   devmem->pagemap.range.start = res->start;
-   devmem->pagemap.range.end = res->end;
devmem->pagemap.nr_range = 1;
devmem->pagemap.ops = &dmirror_devmem_ops;
devmem->pagemap.owner = mdevice;
@@ -497,10 +523,14 @@ static bool dmirror_allocate_chunk(struct dmirror_device 
*mdevice,
mdevice->devmem_capacity = new_capacity;
mdevice->devmem_chunks = new_chunks;
}
-
ptr = memremap_pages(&devmem->pagemap, numa_node_id());
-   if (IS_ERR(ptr))
+   if (IS_ERR_OR_NULL(ptr)) {
+   if (ptr)
+   ret = PTR_ERR(ptr);
+   else
+   ret = -EFAULT;
goto err_release;
+   }
 
devmem->mdevice = mdevice;
pfn_first = devmem->pagemap.range.start >> PAGE_SHIFT;
@@ -529,15 +559,17 @@ static bool dmirror_allocate_chunk(struct dmirror_device 
*mdevice,
}
spin_unlock(&mdevice->lock);
 
-   return true;
+   return 0;
 
 err_release:
mutex_unlock(&mdevice->devmem_lock);
-   release_mem_region(devmem->pagemap.range.start, 
range_len(&devmem->pagemap.range));
+   if (res && devmem->pagemap.type == MEMORY_DEVICE_PRIVATE)
+   release_mem_region(devmem->pagemap.range.start,
+  range_len(&devmem->pagemap.range));
 

[PATCH v5 07/13] lib: test_hmm add ioctl to get zone device type

2022-05-31 Thread Alex Sierra
new ioctl cmd added to query zone device type. This will be
used once the test_hmm adds zone device coherent type.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
Reviewed-by: Alistair Poppple 
Signed-off-by: Christoph Hellwig 
---
 lib/test_hmm.c  | 11 +--
 lib/test_hmm_uapi.h | 14 ++
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/lib/test_hmm.c b/lib/test_hmm.c
index cfe632047839..915ef6b5b0d4 100644
--- a/lib/test_hmm.c
+++ b/lib/test_hmm.c
@@ -87,6 +87,7 @@ struct dmirror_chunk {
 struct dmirror_device {
struct cdev cdevice;
struct hmm_devmem   *devmem;
+   unsigned intzone_device_type;
 
unsigned intdevmem_capacity;
unsigned intdevmem_count;
@@ -1260,14 +1261,20 @@ static void dmirror_device_remove(struct dmirror_device 
*mdevice)
 static int __init hmm_dmirror_init(void)
 {
int ret;
-   int id;
+   int id = 0;
+   int ndevices = 0;
 
ret = alloc_chrdev_region(&dmirror_dev, 0, DMIRROR_NDEVICES,
  "HMM_DMIRROR");
if (ret)
goto err_unreg;
 
-   for (id = 0; id < DMIRROR_NDEVICES; id++) {
+   memset(dmirror_devices, 0, DMIRROR_NDEVICES * 
sizeof(dmirror_devices[0]));
+   dmirror_devices[ndevices++].zone_device_type =
+   HMM_DMIRROR_MEMORY_DEVICE_PRIVATE;
+   dmirror_devices[ndevices++].zone_device_type =
+   HMM_DMIRROR_MEMORY_DEVICE_PRIVATE;
+   for (id = 0; id < ndevices; id++) {
ret = dmirror_device_init(dmirror_devices + id, id);
if (ret)
goto err_chrdev;
diff --git a/lib/test_hmm_uapi.h b/lib/test_hmm_uapi.h
index f14dea5dcd06..0511af7464ee 100644
--- a/lib/test_hmm_uapi.h
+++ b/lib/test_hmm_uapi.h
@@ -31,10 +31,11 @@ struct hmm_dmirror_cmd {
 /* Expose the address space of the calling process through hmm device file */
 #define HMM_DMIRROR_READ   _IOWR('H', 0x00, struct hmm_dmirror_cmd)
 #define HMM_DMIRROR_WRITE  _IOWR('H', 0x01, struct hmm_dmirror_cmd)
-#define HMM_DMIRROR_MIGRATE_IOWR('H', 0x02, struct hmm_dmirror_cmd)
-#define HMM_DMIRROR_SNAPSHOT   _IOWR('H', 0x03, struct hmm_dmirror_cmd)
-#define HMM_DMIRROR_EXCLUSIVE  _IOWR('H', 0x04, struct hmm_dmirror_cmd)
-#define HMM_DMIRROR_CHECK_EXCLUSIVE_IOWR('H', 0x05, struct hmm_dmirror_cmd)
+#define HMM_DMIRROR_MIGRATE_TO_DEV _IOWR('H', 0x02, struct hmm_dmirror_cmd)
+#define HMM_DMIRROR_MIGRATE_TO_SYS _IOWR('H', 0x03, struct hmm_dmirror_cmd)
+#define HMM_DMIRROR_SNAPSHOT   _IOWR('H', 0x04, struct hmm_dmirror_cmd)
+#define HMM_DMIRROR_EXCLUSIVE  _IOWR('H', 0x05, struct hmm_dmirror_cmd)
+#define HMM_DMIRROR_CHECK_EXCLUSIVE_IOWR('H', 0x06, struct hmm_dmirror_cmd)
 
 /*
  * Values returned in hmm_dmirror_cmd.ptr for HMM_DMIRROR_SNAPSHOT.
@@ -62,4 +63,9 @@ enum {
HMM_DMIRROR_PROT_DEV_PRIVATE_REMOTE = 0x30,
 };
 
+enum {
+   /* 0 is reserved to catch uninitialized type fields */
+   HMM_DMIRROR_MEMORY_DEVICE_PRIVATE = 1,
+};
+
 #endif /* _LIB_TEST_HMM_UAPI_H */
-- 
2.32.0



[PATCH v5 13/13] tools: add selftests to hmm for COW in device memory

2022-05-31 Thread Alex Sierra
The objective is to test device migration mechanism in pages marked
as COW, for private and coherent device type. In case of writing to
COW private page(s), a page fault will migrate pages back to system
memory first. Then, these pages will be duplicated. In case of COW
device coherent type, pages are duplicated directly from device
memory.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
---
 tools/testing/selftests/vm/hmm-tests.c | 80 ++
 1 file changed, 80 insertions(+)

diff --git a/tools/testing/selftests/vm/hmm-tests.c 
b/tools/testing/selftests/vm/hmm-tests.c
index 3295c8bf6c63..2da9d5baf339 100644
--- a/tools/testing/selftests/vm/hmm-tests.c
+++ b/tools/testing/selftests/vm/hmm-tests.c
@@ -1869,4 +1869,84 @@ TEST_F(hmm, hmm_gup_test)
close(gup_fd);
hmm_buffer_free(buffer);
 }
+
+/*
+ * Test copy-on-write in device pages.
+ * In case of writing to COW private page(s), a page fault will migrate pages
+ * back to system memory first. Then, these pages will be duplicated. In case
+ * of COW device coherent type, pages are duplicated directly from device
+ * memory.
+ */
+TEST_F(hmm, hmm_cow_in_device)
+{
+   struct hmm_buffer *buffer;
+   unsigned long npages;
+   unsigned long size;
+   unsigned long i;
+   int *ptr;
+   int ret;
+   unsigned char *m;
+   pid_t pid;
+   int status;
+
+   npages = 4;
+   size = npages << self->page_shift;
+
+   buffer = malloc(sizeof(*buffer));
+   ASSERT_NE(buffer, NULL);
+
+   buffer->fd = -1;
+   buffer->size = size;
+   buffer->mirror = malloc(size);
+   ASSERT_NE(buffer->mirror, NULL);
+
+   buffer->ptr = mmap(NULL, size,
+  PROT_READ | PROT_WRITE,
+  MAP_PRIVATE | MAP_ANONYMOUS,
+  buffer->fd, 0);
+   ASSERT_NE(buffer->ptr, MAP_FAILED);
+
+   /* Initialize buffer in system memory. */
+   for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
+   ptr[i] = i;
+
+   /* Migrate memory to device. */
+
+   ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
+   ASSERT_EQ(ret, 0);
+   ASSERT_EQ(buffer->cpages, npages);
+
+   pid = fork();
+   if (pid == -1)
+   ASSERT_EQ(pid, 0);
+   if (!pid) {
+   /* Child process waitd for SIGTERM from the parent. */
+   while (1) {
+   }
+   perror("Should not reach this\n");
+   exit(0);
+   }
+   /* Parent process writes to COW pages(s) and gets a
+* new copy in system. In case of device private pages,
+* this write causes a migration to system mem first.
+*/
+   for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
+   ptr[i] = i;
+
+   /* Terminate child and wait */
+   EXPECT_EQ(0, kill(pid, SIGTERM));
+   EXPECT_EQ(pid, waitpid(pid, &status, 0));
+   EXPECT_NE(0, WIFSIGNALED(status));
+   EXPECT_EQ(SIGTERM, WTERMSIG(status));
+
+   /* Take snapshot to CPU pagetables */
+   ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages);
+   ASSERT_EQ(ret, 0);
+   ASSERT_EQ(buffer->cpages, npages);
+   m = buffer->mirror;
+   for (i = 0; i < npages; i++)
+   ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[i]);
+
+   hmm_buffer_free(buffer);
+}
 TEST_HARNESS_MAIN
-- 
2.32.0



[PATCH v5 10/13] tools: update hmm-test to support device coherent type

2022-05-31 Thread Alex Sierra
Test cases such as migrate_fault and migrate_multiple, were modified to
explicit migrate from device to sys memory without the need of page
faults, when using device coherent type.

Snapshot test case updated to read memory device type first and based
on that, get the proper returned results migrate_ping_pong test case
added to test explicit migration from device to sys memory for both
private and coherent zone types.

Helpers to migrate from device to sys memory and vicerversa
were also added.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
Reviewed-by: Alistair Popple 
Signed-off-by: Christoph Hellwig 
---
 tools/testing/selftests/vm/hmm-tests.c | 121 -
 1 file changed, 100 insertions(+), 21 deletions(-)

diff --git a/tools/testing/selftests/vm/hmm-tests.c 
b/tools/testing/selftests/vm/hmm-tests.c
index 203323967b50..4b547188ec40 100644
--- a/tools/testing/selftests/vm/hmm-tests.c
+++ b/tools/testing/selftests/vm/hmm-tests.c
@@ -46,6 +46,13 @@ struct hmm_buffer {
uint64_tfaults;
 };
 
+enum {
+   HMM_PRIVATE_DEVICE_ONE,
+   HMM_PRIVATE_DEVICE_TWO,
+   HMM_COHERENCE_DEVICE_ONE,
+   HMM_COHERENCE_DEVICE_TWO,
+};
+
 #define TWOMEG (1 << 21)
 #define HMM_BUFFER_SIZE (1024 << 12)
 #define HMM_PATH_MAX64
@@ -60,6 +67,21 @@ FIXTURE(hmm)
unsigned intpage_shift;
 };
 
+FIXTURE_VARIANT(hmm)
+{
+   int device_number;
+};
+
+FIXTURE_VARIANT_ADD(hmm, hmm_device_private)
+{
+   .device_number = HMM_PRIVATE_DEVICE_ONE,
+};
+
+FIXTURE_VARIANT_ADD(hmm, hmm_device_coherent)
+{
+   .device_number = HMM_COHERENCE_DEVICE_ONE,
+};
+
 FIXTURE(hmm2)
 {
int fd0;
@@ -68,6 +90,24 @@ FIXTURE(hmm2)
unsigned intpage_shift;
 };
 
+FIXTURE_VARIANT(hmm2)
+{
+   int device_number0;
+   int device_number1;
+};
+
+FIXTURE_VARIANT_ADD(hmm2, hmm2_device_private)
+{
+   .device_number0 = HMM_PRIVATE_DEVICE_ONE,
+   .device_number1 = HMM_PRIVATE_DEVICE_TWO,
+};
+
+FIXTURE_VARIANT_ADD(hmm2, hmm2_device_coherent)
+{
+   .device_number0 = HMM_COHERENCE_DEVICE_ONE,
+   .device_number1 = HMM_COHERENCE_DEVICE_TWO,
+};
+
 static int hmm_open(int unit)
 {
char pathname[HMM_PATH_MAX];
@@ -81,12 +121,19 @@ static int hmm_open(int unit)
return fd;
 }
 
+static bool hmm_is_coherent_type(int dev_num)
+{
+   return (dev_num >= HMM_COHERENCE_DEVICE_ONE);
+}
+
 FIXTURE_SETUP(hmm)
 {
self->page_size = sysconf(_SC_PAGE_SIZE);
self->page_shift = ffs(self->page_size) - 1;
 
-   self->fd = hmm_open(0);
+   self->fd = hmm_open(variant->device_number);
+   if (self->fd < 0 && hmm_is_coherent_type(variant->device_number))
+   SKIP(exit(0), "DEVICE_COHERENT not available");
ASSERT_GE(self->fd, 0);
 }
 
@@ -95,9 +142,11 @@ FIXTURE_SETUP(hmm2)
self->page_size = sysconf(_SC_PAGE_SIZE);
self->page_shift = ffs(self->page_size) - 1;
 
-   self->fd0 = hmm_open(0);
+   self->fd0 = hmm_open(variant->device_number0);
+   if (self->fd0 < 0 && hmm_is_coherent_type(variant->device_number0))
+   SKIP(exit(0), "DEVICE_COHERENT not available");
ASSERT_GE(self->fd0, 0);
-   self->fd1 = hmm_open(1);
+   self->fd1 = hmm_open(variant->device_number1);
ASSERT_GE(self->fd1, 0);
 }
 
@@ -211,6 +260,20 @@ static void hmm_nanosleep(unsigned int n)
nanosleep(&t, NULL);
 }
 
+static int hmm_migrate_sys_to_dev(int fd,
+  struct hmm_buffer *buffer,
+  unsigned long npages)
+{
+   return hmm_dmirror_cmd(fd, HMM_DMIRROR_MIGRATE_TO_DEV, buffer, npages);
+}
+
+static int hmm_migrate_dev_to_sys(int fd,
+  struct hmm_buffer *buffer,
+  unsigned long npages)
+{
+   return hmm_dmirror_cmd(fd, HMM_DMIRROR_MIGRATE_TO_SYS, buffer, npages);
+}
+
 /*
  * Simple NULL test of device open/close.
  */
@@ -875,7 +938,7 @@ TEST_F(hmm, migrate)
ptr[i] = i;
 
/* Migrate memory to device. */
-   ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_MIGRATE, buffer, npages);
+   ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
ASSERT_EQ(ret, 0);
ASSERT_EQ(buffer->cpages, npages);
 
@@ -923,7 +986,7 @@ TEST_F(hmm, migrate_fault)
ptr[i] = i;
 
/* Migrate memory to device. */
-   ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_MIGRATE, buffer, npages);
+   ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
ASSERT_EQ(ret, 0);
ASSERT_EQ(buffer->cpages, npages);
 
@@ -936,7 +999,7 @@ TEST_F(hmm, migrate_fault)
ASSERT_EQ(ptr[i], i);
 
/* Migrate memory to the device again. */
-   ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_MIGRATE, buffer, npages);
+   ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
ASSERT_EQ(ret, 0);
ASSERT_EQ(buffer->cpages, 

[PATCH v5 09/13] lib: add support for device coherent type in test_hmm

2022-05-31 Thread Alex Sierra
Device Coherent type uses device memory that is coherently accesible by
the CPU. This could be shown as SP (special purpose) memory range
at the BIOS-e820 memory enumeration. If no SP memory is supported in
system, this could be faked by setting CONFIG_EFI_FAKE_MEMMAP.

Currently, test_hmm only supports two different SP ranges of at least
256MB size. This could be specified in the kernel parameter variable
efi_fake_mem. Ex. Two SP ranges of 1GB starting at 0x1 &
0x14000 physical address. Ex.
efi_fake_mem=1G@0x1:0x4,1G@0x14000:0x4

Private and coherent device mirror instances can be created in the same
probed. This is done by passing the module parameters spm_addr_dev0 &
spm_addr_dev1. In this case, it will create four instances of
device_mirror. The first two correspond to private device type, the
last two to coherent type. Then, they can be easily accessed from user
space through /dev/hmm_mirror. Usually num_device 0 and 1
are for private, and 2 and 3 for coherent types. If no module
parameters are passed, two instances of private type device_mirror will
be created only.

Signed-off-by: Alex Sierra 
Acked-by: Felix Kuehling 
Reviewed-by: Alistair Poppple 
---
 lib/test_hmm.c  | 253 +---
 lib/test_hmm_uapi.h |   4 +
 2 files changed, 196 insertions(+), 61 deletions(-)

diff --git a/lib/test_hmm.c b/lib/test_hmm.c
index afb30af9f3ff..7930853e7fc5 100644
--- a/lib/test_hmm.c
+++ b/lib/test_hmm.c
@@ -32,11 +32,22 @@
 
 #include "test_hmm_uapi.h"
 
-#define DMIRROR_NDEVICES   2
+#define DMIRROR_NDEVICES   4
 #define DMIRROR_RANGE_FAULT_TIMEOUT1000
 #define DEVMEM_CHUNK_SIZE  (256 * 1024 * 1024U)
 #define DEVMEM_CHUNKS_RESERVE  16
 
+/*
+ * For device_private pages, dpage is just a dummy struct page
+ * representing a piece of device memory. dmirror_devmem_alloc_page
+ * allocates a real system memory page as backing storage to fake a
+ * real device. zone_device_data points to that backing page. But
+ * for device_coherent memory, the struct page represents real
+ * physical CPU-accessible memory that we can use directly.
+ */
+#define BACKING_PAGE(page) (is_device_private_page((page)) ? \
+  (page)->zone_device_data : (page))
+
 static unsigned long spm_addr_dev0;
 module_param(spm_addr_dev0, long, 0644);
 MODULE_PARM_DESC(spm_addr_dev0,
@@ -125,6 +136,21 @@ static int dmirror_bounce_init(struct dmirror_bounce 
*bounce,
return 0;
 }
 
+static bool dmirror_is_private_zone(struct dmirror_device *mdevice)
+{
+   return (mdevice->zone_device_type ==
+   HMM_DMIRROR_MEMORY_DEVICE_PRIVATE) ? true : false;
+}
+
+static enum migrate_vma_direction
+dmirror_select_device(struct dmirror *dmirror)
+{
+   return (dmirror->mdevice->zone_device_type ==
+   HMM_DMIRROR_MEMORY_DEVICE_PRIVATE) ?
+   MIGRATE_VMA_SELECT_DEVICE_PRIVATE :
+   MIGRATE_VMA_SELECT_DEVICE_COHERENT;
+}
+
 static void dmirror_bounce_fini(struct dmirror_bounce *bounce)
 {
vfree(bounce->ptr);
@@ -575,16 +601,19 @@ static int dmirror_allocate_chunk(struct dmirror_device 
*mdevice,
 static struct page *dmirror_devmem_alloc_page(struct dmirror_device *mdevice)
 {
struct page *dpage = NULL;
-   struct page *rpage;
+   struct page *rpage = NULL;
 
/*
-* This is a fake device so we alloc real system memory to store
-* our device memory.
+* For ZONE_DEVICE private type, this is a fake device so we allocate
+* real system memory to store our device memory.
+* For ZONE_DEVICE coherent type we use the actual dpage to store the
+* data and ignore rpage.
 */
-   rpage = alloc_page(GFP_HIGHUSER);
-   if (!rpage)
-   return NULL;
-
+   if (dmirror_is_private_zone(mdevice)) {
+   rpage = alloc_page(GFP_HIGHUSER);
+   if (!rpage)
+   return NULL;
+   }
spin_lock(&mdevice->lock);
 
if (mdevice->free_pages) {
@@ -603,7 +632,8 @@ static struct page *dmirror_devmem_alloc_page(struct 
dmirror_device *mdevice)
return dpage;
 
 error:
-   __free_page(rpage);
+   if (rpage)
+   __free_page(rpage);
return NULL;
 }
 
@@ -629,12 +659,16 @@ static void dmirror_migrate_alloc_and_copy(struct 
migrate_vma *args,
 * unallocated pte_none() or read-only zero page.
 */
spage = migrate_pfn_to_page(*src);
+   if (WARN(spage && is_zone_device_page(spage),
+"page already in device spage pfn: 0x%lx\n",
+page_to_pfn(spage)))
+   continue;
 
dpage = dmirror_devmem_alloc_page(mdevice);
if (!dpage)
continue;
 
-   rpage = dpage->zone_device_data;
+   rpage = BACKING_PAGE(dpage);
   

  1   2   >