[PATCH] MAINTAINERS: rectify entries for ARM DRM DRIVERS after dt conversion

2022-05-31 Thread Lukas Bulwahn
The three commits:

  36fd2a65bcaf ("dt-bindings: display: convert Arm HDLCD to DT schema")
  0f6983509ea1 ("dt-bindings: display: convert Arm Komeda to DT schema")
  2c8b082a3ab1 ("dt-bindings: display: convert Arm Mali-DP to DT schema")

convert the arm display dt-bindings, arm,*.txt to arm,*.yaml, but miss to
adjust its reference in MAINTAINERS.

Hence, ./scripts/get_maintainer.pl --self-test=patterns complains about
broken references.

Repair these file references in ARM HDLCD DRM DRIVER, ARM KOMEDA DRM-KMS
DRIVER and ARM MALI-DP DRM DRIVER.

Signed-off-by: Lukas Bulwahn 
---
Andre, please ack.
Rob, Krzysztof, please pick this minor non-urgent clean-up patch in
your -next dt tree.

 MAINTAINERS | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index ae685aaf8850..58e751b9346e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1510,7 +1510,7 @@ F:drivers/clocksource/arm_arch_timer.c
 ARM HDLCD DRM DRIVER
 M: Liviu Dudau 
 S: Supported
-F: Documentation/devicetree/bindings/display/arm,hdlcd.txt
+F: Documentation/devicetree/bindings/display/arm,hdlcd.yaml
 F: drivers/gpu/drm/arm/hdlcd_*
 
 ARM INTEGRATOR, VERSATILE AND REALVIEW SUPPORT
@@ -1545,7 +1545,7 @@ M:Mihail Atanassov 
 L: Mali DP Maintainers 
 S: Supported
 T: git git://anongit.freedesktop.org/drm/drm-misc
-F: Documentation/devicetree/bindings/display/arm,komeda.txt
+F: Documentation/devicetree/bindings/display/arm,komeda.yaml
 F: Documentation/gpu/komeda-kms.rst
 F: drivers/gpu/drm/arm/display/include/
 F: drivers/gpu/drm/arm/display/komeda/
@@ -1567,7 +1567,7 @@ M:Brian Starkey 
 L: Mali DP Maintainers 
 S: Supported
 T: git git://anongit.freedesktop.org/drm/drm-misc
-F: Documentation/devicetree/bindings/display/arm,malidp.txt
+F: Documentation/devicetree/bindings/display/arm,malidp.yaml
 F: Documentation/gpu/afbc.rst
 F: drivers/gpu/drm/arm/
 
-- 
2.17.1



RE: [PATCH] BACKPORT: drm/amdgpu/disply: set num_crtc earlier

2022-05-31 Thread Lin, Tsung-hua (Ryan)
[AMD Official Use Only - General]

Hi Greg,

Thanks for your advice. I have modified the commit and submitted it to Gerrit 
and it's under code review now.

Many thanks,
Ryan Lin.

-Original Message-
From: Greg KH  
Sent: Monday, May 30, 2022 9:05 PM
To: Lin, Tsung-hua (Ryan) 
Cc: Li, Leon ; Swarnakar, Praful ; 
S, Shirish ; Li, Ching-shih (Louis) ; 
Deucher, Alexander ; Daniel Vetter 
; Kazlauskas, Nicholas ; 
sta...@vger.kernel.org; Wentland, Harry ; Li, Sun peng 
(Leo) ; Koenig, Christian ; David 
(ChunMing) Zhou ; David Airlie ; Bas 
Nieuwenhuizen ; Sean Paul ; 
Sasha Levin ; Mark Yacoub ; Li, Roman 
; Ikshwaku Chauhan 
; Simon Ser 
; amd-...@lists.freedesktop.org; 
dri-devel@lists.freedesktop.org; linux-ker...@vger.kernel.org
Subject: Re: [PATCH] BACKPORT: drm/amdgpu/disply: set num_crtc earlier

On Mon, May 30, 2022 at 05:29:02PM +0800, Ryan Lin wrote:
> From: Alex Deucher 
> 
> To avoid a recently added warning:
>  Bogus possible_crtcs: [ENCODER:65:TMDS-65] possible_crtcs=0xf (full 
> crtc mask=0x7)
>  WARNING: CPU: 3 PID: 439 at drivers/gpu/drm/drm_mode_config.c:617 
> drm_mode_config_validate+0x178/0x200 [drm] In this case the warning is 
> harmless, but confusing to users.
> 
> Fixes: 0df108237433 ("drm: Validate encoder->possible_crtcs")
> Bug: 
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugz
> illa.kernel.org%2Fshow_bug.cgi%3Fid%3D209123data=05%7C01%7Ctsung-
> hua.lin%40amd.com%7Cad089e5485984cd0cc1f08da423d097f%7C3dd8961fe4884e6
> 08e11a82d994e183d%7C0%7C0%7C637895127184900879%7CUnknown%7CTWFpbGZsb3d
> 8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C
> 3000%7C%7C%7Csdata=0UcR%2BZszfxXaFz6LUqGq5eYgeqxDdrhySBL7mDmFPKc%
> 3Dreserved=0
> Reviewed-by: Daniel Vetter 
> Reviewed-by: Nicholas Kazlauskas 
> Signed-off-by: Alex Deucher 
> Cc: sta...@vger.kernel.org


Why did you not sign off on this?

And what is the git id of this in Linus's tree?

> Conflicts:
>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>   [Ryan Lin: Fixed the conflict, remove the non-main changed part
>   of this patch]

No need for this here, right?

thanks,

greg k-h


[PATCH v2 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 
---
changes in v2:
- call of_node_put() after of_find_device_by_node() and error paths
before of_find_device_by_node();
---
 drivers/gpu/drm/meson/meson_encoder_hdmi.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c 
b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
index 5e306de6f485..0d532e8e8cca 100644
--- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
@@ -365,7 +365,8 @@ int meson_encoder_hdmi_init(struct meson_drm *priv)
meson_encoder_hdmi->next_bridge = of_drm_find_bridge(remote);
if (!meson_encoder_hdmi->next_bridge) {
dev_err(priv->dev, "Failed to find HDMI transceiver bridge\n");
-   return -EPROBE_DEFER;
+   ret = -EPROBE_DEFER;
+   goto err_put_node;
}
 
/* HDMI Encoder Bridge */
@@ -383,7 +384,7 @@ int meson_encoder_hdmi_init(struct meson_drm *priv)
  DRM_MODE_ENCODER_TMDS);
if (ret) {
dev_err(priv->dev, "Failed to init HDMI encoder: %d\n", ret);
-   return ret;
+   goto err_put_node;
}
 
meson_encoder_hdmi->encoder.possible_crtcs = BIT(0);
@@ -393,7 +394,7 @@ int meson_encoder_hdmi_init(struct meson_drm *priv)
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret) {
dev_err(priv->dev, "Failed to attach bridge: %d\n", ret);
-   return ret;
+   goto err_put_node;
}
 
/* Initialize & attach Bridge Connector */
@@ -401,7 +402,8 @@ int meson_encoder_hdmi_init(struct meson_drm *priv)

_encoder_hdmi->encoder);
if (IS_ERR(meson_encoder_hdmi->connector)) {
dev_err(priv->dev, "Unable to create HDMI bridge connector\n");
-   return PTR_ERR(meson_encoder_hdmi->connector);
+   ret = PTR_ERR(meson_encoder_hdmi->connector);
+   goto err_put_node;
}
drm_connector_attach_encoder(meson_encoder_hdmi->connector,
 _encoder_hdmi->encoder);
@@ -428,6 +430,7 @@ int meson_encoder_hdmi_init(struct meson_drm *priv)
meson_encoder_hdmi->connector->ycbcr_420_allowed = true;
 
pdev = of_find_device_by_node(remote);
+   of_node_put(remote);
if (pdev) {
struct cec_connector_info conn_info;
struct cec_notifier *notifier;
@@ -444,4 +447,8 @@ int meson_encoder_hdmi_init(struct meson_drm *priv)
dev_dbg(priv->dev, "HDMI encoder initialized\n");
 
return 0;
+
+err_put_node:
+   of_node_put(remote);
+   return ret;
 }
-- 
2.25.1



[PATCH v2 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 v2 0/2] drm/meson: Fix refcount leak

2022-05-31 Thread Miaoqian Lin
The following patchset fix two refcount leak bugs.
The cause of the bugs are missing of_node_put() 
after of_graph_get_remote_node().

changes in v2:
- patch#2:Fixed patch in meson_encoder_hdmi_init, call of_node_put() 
  after of_find_device_by_node() and error paths before that. 
  noted by Martin Blumenstingl 

(patch#1: no changes since v1)

v1 link:
patch#1: https://lore.kernel.org/r/20220531144818.26943-1-linmq...@gmail.com/ 
patch#2: https://lore.kernel.org/r/20220531144818.26943-2-linmq...@gmail.com/


Miaoqian Lin (2):
  drm/meson: encoder_cvbs: Fix refcount leak in meson_encoder_cvbs_init
  drm/meson: encoder_hdmi: Fix refcount leak in meson_encoder_hdmi_init

 drivers/gpu/drm/meson/meson_encoder_cvbs.c |  1 +
 drivers/gpu/drm/meson/meson_encoder_hdmi.c | 15 +++
 2 files changed, 12 insertions(+), 4 deletions(-)

-- 
2.25.1



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

2022-05-31 Thread Stephen Boyd
Quoting Douglas Anderson (2022-05-31 16:01:26)
> 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 
> ---

Reviewed-by: Stephen Boyd 


[PATCH] drm: bridge: adv7511: Add check for mipi_dsi_driver_register

2022-05-31 Thread Jiasheng Jiang
As mipi_dsi_driver_register could return error if fails,
it should be better to check the return value and return error
if fails.

Fixes: 1e4d58cd7f88 ("drm/bridge: adv7533: Create a MIPI DSI device")
Signed-off-by: Jiasheng Jiang 
---
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c 
b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 5bb9300040dd..795855b41eb2 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -1392,8 +1392,13 @@ static struct i2c_driver adv7511_driver = {
 
 static int __init adv7511_init(void)
 {
-   if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
-   mipi_dsi_driver_register(_dsi_driver);
+   int ret;
+
+   if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) {
+   ret = mipi_dsi_driver_register(_dsi_driver);
+   if (ret)
+   return ret;
+   }
 
return i2c_add_driver(_driver);
 }
-- 
2.25.1



[PATCH] drm/panel/raspberrypi-touchscreen: Add check for mipi_dsi_driver_register

2022-05-31 Thread Jiasheng Jiang
As mipi_dsi_driver_register could return error if fails,
it should be better to check the return value and return error
if fails.

Fixes: 2f733d6194bd ("drm/panel: Add support for the Raspberry Pi 7" 
Touchscreen.")
Signed-off-by: Jiasheng Jiang 
---
 drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c 
b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
index 145047e19394..cc90afbf4b3e 100644
--- a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
+++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
@@ -498,7 +498,12 @@ static struct i2c_driver rpi_touchscreen_driver = {
 
 static int __init rpi_touchscreen_init(void)
 {
-   mipi_dsi_driver_register(_touchscreen_dsi_driver);
+   int ret;
+
+   ret = mipi_dsi_driver_register(_touchscreen_dsi_driver);
+   if (ret)
+   return ret;
+
return i2c_add_driver(_touchscreen_driver);
 }
 module_init(rpi_touchscreen_init);
-- 
2.25.1



RE: [PATCH v2 3/4] soc: visconti: Add Toshiba Visconti AFFINE image processing accelerator

2022-05-31 Thread yuji2.ishikawa
Hi, Hans,

With your advice for DNN accelerator, I prepared some description of AFFINE IPA 
and its usage.

 Handling memory blocks for Visconti5 accelerators (same description for 
DNN accelerator)

Visconti5 Image-Processing-Accelerators do not have fine grained IOMMU, as CPU 
have.
Therefore, memory region to be passed to the accelerators should be physically 
contiguous.
We use DMA-BUF backed by CMA (Contiguous Memory Allocator) to allocate memory 
regions for sharing between CPU/IPAs.
Originally, in v4.19 based implementation, the ION allocator was used to 
allocate DMA-BUF instances.
For the latest implementation, DMA-BUF HEAPS is used.

Two structure types are used to represent memory region passed to drivers.
* struct drv_ipa_buffer_info
  * to describe whole DMA-BUF instance
* struct drv_ipa_addr
  * to describe a memory region in a DMA-BUF instance

for details, see usage sample of each IPA driver


 Image Processing Accelerators overview (same description for DNN 
accelerator)

Visconti5 SoC has following image processing accererators

* AFFINE: 1 input image, 1 output image;
 Affine transform, Homography transform, Polynomial lens distortion, LUT 
transform
* DNN:N input feature vector, N output feature vector;  
 Deep neural network operation
* PYRAMID 3 input image, 3 * N output image;
 Resize grayscale/color image with N different parameters
* DSPIF:  M input image, N output image;
 Various opeations on images
* HOX:1 input image (multi ROI), 1 input dictionary1 likelihood/feature 
vector;  Extended Histogram of Oriented Gradient based pattern matching
* HAMAT:  2 input feature vectors: 1 output corrdinate vector;  
 Hamming distance matching for stereo vision
* FLMAT:  3 input image, N input feature point, N output matched point; 
 Optical flow matching
* SMLDB:  1 input image, N input feature point, N output feature vector;
 Accelerated-KAZE feature descriptor accelerator
* STMAT:  2 input image, 1 output disparity image;  
 Stereo disparity

see [0] Fig 7.2.1 for block diagram (of prototype chip)


 Affine Overview

AFFINE IPA is a proprietary image processing hardware developed by Toshiba.
Visconti5 SoC has 2 instances of AFFINE IPA hardware.
It has 4 operation modes:
  * Affine (Linear) transformation
  * Homography transformation
  * Polynomial lens distortion
  * LUT based transformation
It accepts 1 input image and yields 1 output image at an operation.


 Input / Output

Input: 8bit grayscale or 16bit grayscale image
Output: 8bit grayscale or 16bit grayscale image

AFFINE IPA driver accepts an instance of "struct drv_affine_descriptor" which 
includes input/output images and operation parameters.


 Descriptor Builder at userland

Following APIs are provided to build a descriptor instance at userland.

/* defined in drv_affine_util.h */
int32_t drv_AFFINE_config_descript_init(struct drv_affine_descriptor *desc, 
struct drv_ipa_buffer_info *buffer, int32_t buffer_num);
int32_t drv_AFFINE_config_input_image(struct drv_affine_descriptor *desc, 
struct drv_ipa_addr src_addr, int32_t src_width, int32_t src_height, int32_t 
src_pitch, int32_t src_depth);  
int32_t drv_AFFINE_config_output_image(struct drv_affine_descriptor *desc, 
struct drv_ipa_addr dst_addr, int32_t dst_width, int32_t dst_height, int32_t 
dst_offset_x, int32_t dst_offset_y, uint16_t fill_value, int32_t dst_pitch, 
int32_t dst_depth)
int32_t drv_AFFINE_config_interpolation_mode(...)
int32_t drv_AFFINE_config_linear(...)
int32_t drv_AFFINE_config_homography(...)
int32_t drv_AFFINE_config_undist(...)
int32_t drv_AFFINE_config_table(...)
int32_t drv_AFFINE_config_descript_finalize(struct drv_affine_descriptor *desc)

struct drv_affine_descriptor is defined in drivers/soc/visconti/uapi/affine.h.
I think this header should be placed anywhere else to be collected on "make 
headers_install" action of kernel building.


 Usage sample (without error handlers)

#include 
#include "drv_ipa.h" 
#include "drv_affine.h"
#include "drv_affine_util.h" 

int allocate_buffer(int fd_heap, int size) 
{
struct dma_heap_allocation_data heap_data_in={0};
int ret;

heap_data_in.len = ROUNDUP_POW2(size);
heap_data_in.fd_flags = O_RDWR | O_CLOEXEC;

ret = ioctl(fd_heap, DMA_HEAP_IOCTL_ALLOC, _data_in);
if (ret <0)
return -1;
else
return heap_data_in.fd;
}

void affine_sample(int fd_affine, int fd_src, int fd_dst) 
{
struct drv_ipa_buffer_info bufinfo[2] = {
{.fd=fd_src, .coherent=true, .direction=DRV_IPA_DIR_TO_DEVICE},
{.fd=fd_dst, .coherent=true, .direction=DRV_IPA_DIR_FROM_DEVICE},
};
struct 

RE: [PATCH 0/4] Add Toshiba Visconti DNN image processing accelerator driver

2022-05-31 Thread yuji2.ishikawa
Hi Hans,

Thank you for your advice.
I prepared some description of DNN accelerator and its usage.

 Handling memory blocks for Visconti5 accelerators

Visconti5 Image-Processing-Accelerators do not have fine grained IOMMU, as CPU 
have.
Therefore, memory region to be passed to the accelerators should be physically 
contiguous.
We use DMA-BUF backed by CMA (Contiguous Memory Allocator) to allocate memory 
regions for sharing between CPU/IPAs.
Originally, in v4.19 based implementation, the ION allocator was used to 
allocate DMA-BUF instances.
For the latest implementation, DMA-BUF HEAPS is used.

Two structure types are used to represent memory region passed to drivers.
* struct drv_ipa_buffer_info
  * to describe whole DMA-BUF instance
* struct drv_ipa_addr
  * to describe a memory region in a DMA-BUF instance

for details, see usage sample of each IPA driver


 Image Processing Accelerators overview

Visconti5 SoC has following image processing accererators

* AFFINE: 1 input image, 1 output image;
 Affine transform, Homography transform, Polynomial lens distortion, LUT 
transform
* DNN:N input feature vector, N output feature vector;  
 Deep neural network operation
* PYRAMID 3 input image, 3 * N output image;
 Resize grayscale/color image with N different parameters
* DSPIF:  M input image, N output image;
 Various opeations on images
* HOX:1 input image (multi ROI), 1 input dictionary1 likelihood/feature 
vector;  Extended Histogram of Oriented Gradient based pattern matching
* HAMAT:  2 input feature vectors: 1 output corrdinate vector;  
 Hamming distance matching for stereo vision
* FLMAT:  3 input image, N input feature point, N output matched point; 
 Optical flow matching
* SMLDB:  1 input image, N input feature point, N output feature vector;
 Accelerated-KAZE feature descriptor accelerator
* STMAT:  2 input image, 1 output disparity image;  
 Stereo disparity

see [0] Fig 7.2.1 for block diagram (of prototype chip)


 DNN accelerator overview

DNN accelerator is a proprietary CNN/DCNN processing accelerator developed by 
Toshiba.
Visconti5 SoC has 2 instances of DNN acclerator hardware.
Users convert existing Caffe/ONNX models to Visconti compatible models with an 
offline tool.
A converted model "Configuration Binary" includes:
  * instruction sequence for given network
  * weight/bias information
  * DMA configuration from/to global memory (for input/output feature)

DNN acccelerator can handle either 1 plane or multiple ROIs at a single call.

see [0] Fig 7.2.2 for block diagram of DNN accelerator

CNN: Convolutional Neural Network
DCNN: Deep Convolutional Neural Network


 Input / Output

Input image or feature: base type is either of FP16, FP32, INT8, UINT8, INT16
Output feature vector:  base type is either of FP16, FP32, INT8, UINT8, INT16

Input, Output, Weight, Bias can be placed on global memory and loaded/stored 
with DMA within DNN accelerator.
These data on global memory can be specified as either of:
  * single address to point single data block
  * list of address to point multiple data blocks (i.e. ROIs)

DNN acclerator driver accepts an instance of "struct drv_dnn_descriptor" which 
includes addresses of input/output features and a configuration binary.


 Descriptor Builder at userland

Following APIs are provided to build a descriptor instance at userland.

/* defined in drv_dnn_util.h */
int32_t drv_DNN_config_descript_init(struct drv_dnn_descriptor *desc, struct 
drv_ipa_buffer_info *buffer, int32_t buffer_num);
int32_t drv_DNN_config_exec_configuration(struct drv_dnn_descriptor *desc, 
const void *configuration_binary,
  struct drv_ipa_addr 
configuration_binary_addr, struct drv_ipa_addr *src_list,
  struct drv_ipa_addr *dst_list, 
int32_t list_num, struct drv_ipa_addr temporary_addr,
  int32_t temporary_size);
int32_t drv_DNN_config_descript_finalize(struct drv_dnn_descriptor *desc);

struct drv_dnn_descriptor is defined in drivers/soc/visconti/uapi/dnn.h.
I think this header should be placed anywhere else to be collected on "make 
headers_install" action of kernel building.


 Usage sample (without error handlers)

#include 
#include "drv_ipa.h"
#include "drv_dnn.h"
#include "drv_dnn_util.h" 

int allocate_buffer(int fd_heap, int size) 
{
struct dma_heap_allocation_data heap_data_in={0};
int ret;

heap_data_in.len = ROUNDUP_POW2(size);
heap_data_in.fd_flags = O_RDWR | O_CLOEXEC;

ret = ioctl(fd_heap, DMA_HEAP_IOCTL_ALLOC, _data_in);
if (ret <0)
return -1;
else
return heap_data_in.fd;
}


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

2022-05-31 Thread Jessica Zhang




On 5/31/2022 4:01 PM, Douglas Anderson wrote:

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 


Tested-by: Jessica Zhang  # RB3 (sdm845) and 
RB5  (qrb5165)



---

Changes in v2:
- Don't set bandwidth in init.

  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  8 
  drivers/gpu/drm/msm/msm_mdss.c  | 57 +
  2 files changed, 57 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 

[RFC PATCH 5/5] drm/amdgpu: Add option to disable implicit sync for a context.

2022-05-31 Thread Bas Nieuwenhuizen
This changes all BO usages in a submit to BOOKKEEP instead of READ,
which effectively disables implicit sync for these submits.

This is configured at a context level using the existing IOCTL.

Signed-off-by: Bas Nieuwenhuizen 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c  | 13 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 32 +++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h |  1 +
 include/uapi/drm/amdgpu_drm.h   |  3 +++
 4 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 64419f55606f..944028d0ed6d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -498,6 +498,7 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
struct amdgpu_bo *gws;
struct amdgpu_bo *oa;
int r;
+   enum dma_resv_usage resv_usage;
 
INIT_LIST_HEAD(>validated);
 
@@ -518,13 +519,16 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser 
*p,
return r;
}
 
+   resv_usage = p->ctx->disable_implicit_sync ? DMA_RESV_USAGE_BOOKKEEP :
+DMA_RESV_USAGE_READ;
+
amdgpu_bo_list_for_each_entry(e, p->bo_list)
-   e->tv.usage = DMA_RESV_USAGE_READ;
+   e->tv.usage = resv_usage;
 
amdgpu_bo_list_get_list(p->bo_list, >validated);
 
INIT_LIST_HEAD();
-   amdgpu_vm_get_pd_bo(>vm, >validated, >vm_pd, 
DMA_RESV_USAGE_READ);
+   amdgpu_vm_get_pd_bo(>vm, >validated, >vm_pd, resv_usage);
 
if (p->uf_entry.tv.bo && !ttm_to_amdgpu_bo(p->uf_entry.tv.bo)->parent)
list_add(>uf_entry.tv.head, >validated);
@@ -651,7 +655,7 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
struct dma_resv *resv = bo->tbo.base.resv;
enum amdgpu_sync_mode sync_mode;
 
-   sync_mode = amdgpu_bo_explicit_sync(bo) ?
+   sync_mode = (amdgpu_bo_explicit_sync(bo) || 
p->ctx->disable_implicit_sync) ?
AMDGPU_SYNC_EXPLICIT : AMDGPU_SYNC_NE_OWNER;
r = amdgpu_sync_resv(p->adev, >job->sync, resv, sync_mode,
 AMDGPU_SYNC_EXPLICIT, >vm);
@@ -1259,7 +1263,8 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
 
/* Make sure all BOs are remembered as writers */
amdgpu_bo_list_for_each_entry(e, p->bo_list)
-   e->tv.usage = DMA_RESV_USAGE_WRITE;
+   e->tv.usage = p->ctx->disable_implicit_sync ? 
DMA_RESV_USAGE_BOOKKEEP
+   : 
DMA_RESV_USAGE_WRITE;
 
ttm_eu_fence_buffer_objects(>ticket, >validated, p->fence);
mutex_unlock(>adev->notifier_lock);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
index c317078d1afd..5fd3ad630194 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@ -559,8 +559,6 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev,
return 0;
 }
 
-
-
 static int amdgpu_ctx_stable_pstate(struct amdgpu_device *adev,
struct amdgpu_fpriv *fpriv, uint32_t id,
bool set, u32 *stable_pstate)
@@ -589,6 +587,30 @@ static int amdgpu_ctx_stable_pstate(struct amdgpu_device 
*adev,
return r;
 }
 
+static int amdgpu_ctx_set_implicit_sync(struct amdgpu_device *adev,
+   struct amdgpu_fpriv *fpriv, uint32_t id,
+   bool enable)
+{
+   struct amdgpu_ctx *ctx;
+   struct amdgpu_ctx_mgr *mgr;
+
+   if (!fpriv)
+   return -EINVAL;
+
+   mgr = >ctx_mgr;
+   mutex_lock(>lock);
+   ctx = idr_find(>ctx_handles, id);
+   if (!ctx) {
+   mutex_unlock(>lock);
+   return -EINVAL;
+   }
+
+   ctx->disable_implicit_sync = !enable;
+
+   mutex_unlock(>lock);
+   return 0;
+}
+
 int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
 struct drm_file *filp)
 {
@@ -637,6 +659,12 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
r = amdgpu_ctx_stable_pstate(adev, fpriv, id, true, 
_pstate);
break;
+   case AMDGPU_CTX_OP_SET_IMPLICIT_SYNC:
+   if ((args->in.flags & ~AMDGPU_CTX_IMPICIT_SYNC_ENABLED) || 
args->in.priority)
+   return -EINVAL;
+   r = amdgpu_ctx_set_implicit_sync(adev, fpriv, id,
+args->in.flags & 
~AMDGPU_CTX_IMPICIT_SYNC_ENABLED);
+   break;
default:
return -EINVAL;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h
index 

[RFC PATCH 4/5] drm/amdgpu: Refactor amdgpu_vm_get_pd_bo.

2022-05-31 Thread Bas Nieuwenhuizen
We want to take only a BOOKKEEP usage for contexts that are not
implicitly synced.

Signed-off-by: Bas Nieuwenhuizen 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 9 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c   | 2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c  | 2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c  | 4 ++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c   | 6 --
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h   | 3 ++-
 6 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 92a1b08b3bbc..c47695b37a1c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -921,7 +921,7 @@ static int reserve_bo_and_vm(struct kgd_mem *mem,
ctx->kfd_bo.tv.usage = DMA_RESV_USAGE_READ;
list_add(>kfd_bo.tv.head, >list);
 
-   amdgpu_vm_get_pd_bo(vm, >list, >vm_pd[0]);
+   amdgpu_vm_get_pd_bo(vm, >list, >vm_pd[0], 
DMA_RESV_USAGE_READ);
 
ret = ttm_eu_reserve_buffers(>ticket, >list,
 false, >duplicates);
@@ -992,7 +992,7 @@ static int reserve_bo_and_cond_vms(struct kgd_mem *mem,
continue;
 
amdgpu_vm_get_pd_bo(entry->bo_va->base.vm, >list,
-   >vm_pd[i]);
+   >vm_pd[i], DMA_RESV_USAGE_READ);
i++;
}
 
@@ -2212,7 +2212,7 @@ static int validate_invalid_user_pages(struct 
amdkfd_process_info *process_info)
list_for_each_entry(peer_vm, _info->vm_list_head,
vm_list_node)
amdgpu_vm_get_pd_bo(peer_vm, _list,
-   _bo_list_entries[i++]);
+   _bo_list_entries[i++], 
DMA_RESV_USAGE_READ);
/* Add the userptr_inval_list entries to resv_list */
list_for_each_entry(mem, _info->userptr_inval_list,
validate_list.head) {
@@ -2407,7 +2407,8 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, 
struct dma_fence **ef)
mutex_lock(_info->lock);
list_for_each_entry(peer_vm, _info->vm_list_head,
vm_list_node)
-   amdgpu_vm_get_pd_bo(peer_vm, , _bo_list[i++]);
+   amdgpu_vm_get_pd_bo(peer_vm, , _bo_list[i++],
+   DMA_RESV_USAGE_READ);
 
/* Reserve all BOs and page tables/directory. Add all BOs from
 * kfd_bo_list to ctx.list
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 0318a6d46a41..64419f55606f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -524,7 +524,7 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
amdgpu_bo_list_get_list(p->bo_list, >validated);
 
INIT_LIST_HEAD();
-   amdgpu_vm_get_pd_bo(>vm, >validated, >vm_pd);
+   amdgpu_vm_get_pd_bo(>vm, >validated, >vm_pd, 
DMA_RESV_USAGE_READ);
 
if (p->uf_entry.tv.bo && !ttm_to_amdgpu_bo(p->uf_entry.tv.bo)->parent)
list_add(>uf_entry.tv.head, >validated);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c
index 71277257d94d..f091fe6bb985 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c
@@ -77,7 +77,7 @@ int amdgpu_map_static_csa(struct amdgpu_device *adev, struct 
amdgpu_vm *vm,
csa_tv.usage = DMA_RESV_USAGE_READ;
 
list_add(_tv.head, );
-   amdgpu_vm_get_pd_bo(vm, , );
+   amdgpu_vm_get_pd_bo(vm, , , DMA_RESV_USAGE_READ);
 
r = ttm_eu_reserve_buffers(, , true, NULL);
if (r) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 7483411229f4..a1194a0986bf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -210,7 +210,7 @@ static void amdgpu_gem_object_close(struct drm_gem_object 
*obj,
tv.usage = DMA_RESV_USAGE_READ;
list_add(, );
 
-   amdgpu_vm_get_pd_bo(vm, , _pd);
+   amdgpu_vm_get_pd_bo(vm, , _pd, DMA_RESV_USAGE_READ);
 
r = ttm_eu_reserve_buffers(, , false, );
if (r) {
@@ -740,7 +740,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
abo = NULL;
}
 
-   amdgpu_vm_get_pd_bo(>vm, , _pd);
+   amdgpu_vm_get_pd_bo(>vm, , _pd, DMA_RESV_USAGE_READ);
 
r = ttm_eu_reserve_buffers(, , true, );
if (r)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 515be19ab279..da04072a3ea6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -623,17 +623,19 @@ static void amdgpu_vm_pt_next_dfs(struct amdgpu_device 
*adev,
  * @vm: vm providing 

[RFC PATCH 1/5] drm/ttm: Refactor num_shared into usage.

2022-05-31 Thread Bas Nieuwenhuizen
So that the driver can set some BOOKKEEP for explicit sync. Maybe
some of the existing places would already make sense for that, but
I targeted this for no functional changes.

Signed-off-by: Bas Nieuwenhuizen 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  | 10 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c|  8 +++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c   |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c   |  6 +++---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c  |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c|  3 +--
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c  |  2 +-
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  2 +-
 drivers/gpu/drm/qxl/qxl_release.c |  2 +-
 drivers/gpu/drm/radeon/radeon_cs.c|  5 +++--
 drivers/gpu/drm/radeon/radeon_gem.c   |  2 +-
 drivers/gpu/drm/radeon/radeon_vm.c|  4 ++--
 drivers/gpu/drm/ttm/ttm_execbuf_util.c|  5 ++---
 drivers/gpu/drm/vmwgfx/vmwgfx_resource.c  | 10 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_validation.c|  2 +-
 include/drm/ttm/ttm_execbuf_util.h|  3 ++-
 16 files changed, 33 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index a4955ef76cfc..a790a089e829 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -774,7 +774,7 @@ static void add_kgd_mem_to_kfd_bo_list(struct kgd_mem *mem,
struct amdgpu_bo *bo = mem->bo;
 
INIT_LIST_HEAD(>head);
-   entry->num_shared = 1;
+   entry->usage = DMA_RESV_USAGE_READ;
entry->bo = >tbo;
mutex_lock(_info->lock);
if (userptr)
@@ -918,7 +918,7 @@ static int reserve_bo_and_vm(struct kgd_mem *mem,
 
ctx->kfd_bo.priority = 0;
ctx->kfd_bo.tv.bo = >tbo;
-   ctx->kfd_bo.tv.num_shared = 1;
+   ctx->kfd_bo.tv.usage = DMA_RESV_USAGE_READ;
list_add(>kfd_bo.tv.head, >list);
 
amdgpu_vm_get_pd_bo(vm, >list, >vm_pd[0]);
@@ -981,7 +981,7 @@ static int reserve_bo_and_cond_vms(struct kgd_mem *mem,
 
ctx->kfd_bo.priority = 0;
ctx->kfd_bo.tv.bo = >tbo;
-   ctx->kfd_bo.tv.num_shared = 1;
+   ctx->kfd_bo.tv.usage = DMA_RESV_USAGE_READ;
list_add(>kfd_bo.tv.head, >list);
 
i = 0;
@@ -2218,7 +2218,7 @@ static int validate_invalid_user_pages(struct 
amdkfd_process_info *process_info)
validate_list.head) {
list_add_tail(>resv_list.head, _list);
mem->resv_list.bo = mem->validate_list.bo;
-   mem->resv_list.num_shared = mem->validate_list.num_shared;
+   mem->resv_list.usage = mem->validate_list.usage;
}
 
/* Reserve all BOs and page tables for validation */
@@ -2417,7 +2417,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, 
struct dma_fence **ef)
 
list_add_tail(>resv_list.head, );
mem->resv_list.bo = mem->validate_list.bo;
-   mem->resv_list.num_shared = mem->validate_list.num_shared;
+   mem->resv_list.usage = mem->validate_list.usage;
}
 
ret = ttm_eu_reserve_buffers(, ,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 60ca14afb879..2ae1c0d9d33a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -55,8 +55,7 @@ static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser 
*p,
bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
p->uf_entry.priority = 0;
p->uf_entry.tv.bo = >tbo;
-   /* One for TTM and two for the CS job */
-   p->uf_entry.tv.num_shared = 3;
+   p->uf_entry.tv.usage = DMA_RESV_USAGE_READ;
 
drm_gem_object_put(gobj);
 
@@ -519,9 +518,8 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
return r;
}
 
-   /* One for TTM and one for the CS job */
amdgpu_bo_list_for_each_entry(e, p->bo_list)
-   e->tv.num_shared = 2;
+   e->tv.usage = DMA_RESV_USAGE_READ;
 
amdgpu_bo_list_get_list(p->bo_list, >validated);
 
@@ -1261,7 +1259,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
 
/* Make sure all BOs are remembered as writers */
amdgpu_bo_list_for_each_entry(e, p->bo_list)
-   e->tv.num_shared = 0;
+   e->tv.usage = DMA_RESV_USAGE_WRITE;
 
ttm_eu_fence_buffer_objects(>ticket, >validated, p->fence);
mutex_unlock(>adev->notifier_lock);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c
index c6d4d41c4393..71277257d94d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c
@@ -74,7 +74,7 @@ int amdgpu_map_static_csa(struct 

[RFC PATCH 3/5] drm/amdgpu: Allow explicit sync for VM ops.

2022-05-31 Thread Bas Nieuwenhuizen
This should be okay because moves themselves use KERNEL usage and
hence still sync with BOOKKEEP usage. Then any later submits still
wait on any pending VM operations.

(i.e. we only made VM ops not wait on BOOKKEEP submits, not the other
 way around)

Signed-off-by: Bas Nieuwenhuizen 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c  | 2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c
index f10332e1c6c0..31bc73fd1fae 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c
@@ -51,7 +51,7 @@ static int amdgpu_vm_cpu_prepare(struct 
amdgpu_vm_update_params *p,
if (!resv)
return 0;
 
-   return amdgpu_bo_sync_wait_resv(p->adev, resv, sync_mode, sync_mode, 
p->vm, true);
+   return amdgpu_bo_sync_wait_resv(p->adev, resv, sync_mode, 
AMDGPU_SYNC_EXPLICIT, p->vm, true);
 }
 
 /**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
index 63b484dc76c5..c8d5898bea11 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
@@ -75,7 +75,7 @@ static int amdgpu_vm_sdma_prepare(struct 
amdgpu_vm_update_params *p,
if (!resv)
return 0;
 
-   return amdgpu_sync_resv(p->adev, >job->sync, resv, sync_mode, 
sync_mode, p->vm);
+   return amdgpu_sync_resv(p->adev, >job->sync, resv, sync_mode, 
AMDGPU_SYNC_EXPLICIT, p->vm);
 }
 
 /**
-- 
2.36.1



[RFC PATCH 2/5] drm/amdgpu: Add separate mode for syncing DMA_RESV_USAGE_BOOKKEEP.

2022-05-31 Thread Bas Nieuwenhuizen
To prep for allowing different sync modes in a follow-up patch.

Signed-off-by: Bas Nieuwenhuizen 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c   |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c   | 11 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.h   |  3 ++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 11 ---
 drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h |  4 ++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c  |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c  |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c   |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c  |  2 +-
 10 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index a790a089e829..92a1b08b3bbc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1157,7 +1157,7 @@ static int process_sync_pds_resv(struct 
amdkfd_process_info *process_info,
struct amdgpu_bo *pd = peer_vm->root.bo;
 
ret = amdgpu_sync_resv(NULL, sync, pd->tbo.base.resv,
-  AMDGPU_SYNC_NE_OWNER,
+  AMDGPU_SYNC_NE_OWNER, 
AMDGPU_SYNC_NE_OWNER,
   AMDGPU_FENCE_OWNER_KFD);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 2ae1c0d9d33a..0318a6d46a41 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -654,7 +654,7 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
sync_mode = amdgpu_bo_explicit_sync(bo) ?
AMDGPU_SYNC_EXPLICIT : AMDGPU_SYNC_NE_OWNER;
r = amdgpu_sync_resv(p->adev, >job->sync, resv, sync_mode,
->vm);
+AMDGPU_SYNC_EXPLICIT, >vm);
if (r)
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index 91b99eb7dc35..63e6f7b8b522 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -1407,7 +1407,8 @@ void amdgpu_bo_fence(struct amdgpu_bo *bo, struct 
dma_fence *fence,
  *
  * @adev: amdgpu device pointer
  * @resv: reservation object to sync to
- * @sync_mode: synchronization mode
+ * @implicit_sync_mode: synchronization mode for usage <= DMA_RESV_USAGE_READ
+ * @explicit_sync_mode: synchronization mode for usage DMA_RESV_USAGE_BOOKKEEP
  * @owner: fence owner
  * @intr: Whether the wait is interruptible
  *
@@ -1417,14 +1418,15 @@ void amdgpu_bo_fence(struct amdgpu_bo *bo, struct 
dma_fence *fence,
  * 0 on success, errno otherwise.
  */
 int amdgpu_bo_sync_wait_resv(struct amdgpu_device *adev, struct dma_resv *resv,
-enum amdgpu_sync_mode sync_mode, void *owner,
+enum amdgpu_sync_mode implicit_sync_mode,
+enum amdgpu_sync_mode explicit_sync_mode, void 
*owner,
 bool intr)
 {
struct amdgpu_sync sync;
int r;
 
amdgpu_sync_create();
-   amdgpu_sync_resv(adev, , resv, sync_mode, owner);
+   amdgpu_sync_resv(adev, , resv, implicit_sync_mode, 
explicit_sync_mode, owner);
r = amdgpu_sync_wait(, intr);
amdgpu_sync_free();
return r;
@@ -1445,7 +1447,8 @@ int amdgpu_bo_sync_wait(struct amdgpu_bo *bo, void 
*owner, bool intr)
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
 
return amdgpu_bo_sync_wait_resv(adev, bo->tbo.base.resv,
-   AMDGPU_SYNC_NE_OWNER, owner, intr);
+   AMDGPU_SYNC_NE_OWNER, 
AMDGPU_SYNC_EXPLICIT,
+   owner, intr);
 }
 
 /**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index 4c9cbdc66995..9540ee1102ad 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -321,7 +321,8 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct 
ttm_buffer_object *bo);
 void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
 bool shared);
 int amdgpu_bo_sync_wait_resv(struct amdgpu_device *adev, struct dma_resv *resv,
-enum amdgpu_sync_mode sync_mode, void *owner,
+enum amdgpu_sync_mode implicit_sync_mode,
+enum amdgpu_sync_mode explicit_sync_mode, void 
*owner,
 bool intr);
 int amdgpu_bo_sync_wait(struct amdgpu_bo *bo, void *owner, bool intr);
 u64 

[RFC PATCH 0/5] Add option to disable implicit sync for userspace submits.

2022-05-31 Thread Bas Nieuwenhuizen
This adds a context option to use DMA_RESV_USAGE_BOOKKEEP for userspace 
submissions,
based on Christians TTM work.

Disabling implicit sync is something we've wanted in radv for a while for 
resolving
some corner cases. A more immediate thing that would be solved here is avoiding 
a
bunch of implicit sync on GPU map/unmap operations as well, which helps with 
stutter
around sparse maps/unmaps.

I have experimental userspace in radv, but it isn't 100% ready yet. There are 
still
issues with some games that I'm looking at, but in the meantime I'm looking for 
early
feedback on the idea.

Besides the debugging an open question is whether it is worth adding the option 
to
wait on additional explicit syncobj in the VM map/unmap operations. My current 
radv
code waits on the wait syncobj in userspace on a thread before doing the 
operation
which results in some corner cases because we can't provide binary syncobj at
submission time (impacting the usual sync file exports). However adding these 
fences
adds the risk of head of line blocking because all VM operations get executed 
on the
same ring, so all later operations get blocked by waiting on the fences as 
well, which
can cause head of line blocking.

I'm looking to get more implementation experience with different games to see 
if we
need this, but if we need it it would be a somewhat separate addition to the 
UAPI.

Bas Nieuwenhuizen (5):
  drm/ttm: Refactor num_shared into usage.
  drm/amdgpu: Add separate mode for syncing DMA_RESV_USAGE_BOOKKEEP.
  drm/amdgpu: Allow explicit sync for VM ops.
  drm/amdgpu: Refactor amdgpu_vm_get_pd_bo.
  drm/amdgpu: Add option to disable implicit sync for a context.

 .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  | 21 ++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c| 19 ++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c   |  4 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c   | 32 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h   |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c   | 10 +++---
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c| 11 ---
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.h|  3 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c  | 11 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h  |  4 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c   |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c   |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c  |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c|  7 ++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h|  3 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c|  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c   |  2 +-
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c  |  2 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  2 +-
 drivers/gpu/drm/qxl/qxl_release.c |  2 +-
 drivers/gpu/drm/radeon/radeon_cs.c|  5 +--
 drivers/gpu/drm/radeon/radeon_gem.c   |  2 +-
 drivers/gpu/drm/radeon/radeon_vm.c|  4 +--
 drivers/gpu/drm/ttm/ttm_execbuf_util.c|  5 ++-
 drivers/gpu/drm/vmwgfx/vmwgfx_resource.c  | 10 +++---
 drivers/gpu/drm/vmwgfx/vmwgfx_validation.c|  2 +-
 include/drm/ttm/ttm_execbuf_util.h|  3 +-
 include/uapi/drm/amdgpu_drm.h |  3 ++
 28 files changed, 112 insertions(+), 63 deletions(-)

-- 
2.36.1



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

2022-05-31 Thread Abhinav Kumar

Hi Doug

On 5/31/2022 4:01 PM, Douglas Anderson wrote:

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 

Reviewed-by: Abhinav Kumar 

We will test this out even on RB3/RB5 to make sure it boots up fine and 
give Tested-by.


Thanks

Abhinav


---

Changes in v2:
- Don't set bandwidth in init.

  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  8 
  drivers/gpu/drm/msm/msm_mdss.c  | 57 +
  2 files changed, 57 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 @@ 

[PATCH v2] 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 
---

Changes in v2:
- Don't set bandwidth in init.

 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  8 
 drivers/gpu/drm/msm/msm_mdss.c  | 57 +
 2 files changed, 57 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;
 
-   

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

2022-05-31 Thread Rob Herring
On Tue, 31 May 2022 19:18:52 +0800, ChiaEn Wu wrote:
> 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
> 

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:
./Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml: Unable to find 
schema file matching $id: 
http://devicetree.org/schemas/power/supply/mediatek,mt6370-charger.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/mediatek,mt6370.example.dtb:
 mt6370@34: charger: False schema does not allow {'compatible': 
['mediatek,mt6370-charger'], 'interrupts': [[48], [68], [6]], 
'interrupt-names': ['attach_i', 'uvp_d_evt', 'mivr'], 'io-channels': [[1, 5]], 
'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]], 'phandle': [[2]]}}
From schema: 
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/mediatek,mt6370.example.dtb:
 mt6370@34: tcpc: False schema does not allow {'compatible': 
['mediatek,mt6370-tcpc'], 'interrupts-extended': [[4294967295, 4, 8]], 
'connector': {'compatible': ['usb-c-connector'], 'label': ['USB-C'], 
'vbus-supply': [[2]], 'data-role': ['dual'], 'power-role': ['dual'], 
'try-power-role': ['sink'], 'source-pdos': [[570527844]], 'sink-pdos': 
[[570527944]], 'op-sink-microwatt': [[1000]], 'ports': {'#address-cells': 
[[1]], '#size-cells': [[0]], 'port@0': {'reg': [[0]], 'endpoint': 
{'remote-endpoint': [[4294967295]]}}, 'port@1': {'reg': [[1]], 'endpoint': 
{'remote-endpoint': [[4294967295]]}}, 'port@2': {'reg': [[2]], 'endpoint': 
{'remote-endpoint': [[4294967295]]}
From schema: 
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/mediatek,mt6370.example.dtb:
 mt6370@34: indicator: False schema does not allow {'compatible': 
['mediatek,mt6370-indicator'], '#address-cells': [[1]], '#size-cells': [[0]], 
'multi-led@0': {'reg': [[0]], 'function': ['indicator'], 'color': [[9]], 
'led-max-microamp': [[24000]], '#address-cells': [[1]], '#size-cells': [[0]], 
'mediatek,soft-start': [[3]], 'led@0': {'reg': [[0]], 'color': [[1]]}, 'led@1': 
{'reg': [[1]], 'color': [[2]]}, 'led@2': {'reg': [[2]], 'color': [[3]]}}, 
'led@3': {'reg': [[3]], 'function': ['indicator'], 'color': [[0]], 
'led-max-microamp': [[6000]]}}
From schema: 
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/mediatek,mt6370.example.dtb:
 mt6370@34: flashlight: False schema does not allow {'compatible': 
['mediatek,mt6370-flashlight'], '#address-cells': [[1]], '#size-cells': [[0]], 
'led@0': {'reg': [[0]], 'led-sources': [[0]], 'function': ['flash'], 'color': 
[[0]], 'function-enumerator': [[1]], 'led-max-microamp': [[20]], 
'flash-max-microamp': [[50]], 'flash-max-timeout-us': [[1248000]]}, 
'led@1': {'reg': [[1]], 'led-sources': [[1]], 'function': ['flash'], 'color': 
[[0]], 'function-enumerator': [[2]], 'led-max-microamp': [[20]], 
'flash-max-microamp': [[50]], 'flash-max-timeout-us': [[1248000]]}}
From schema: 
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
Documentation/devicetree/bindings/mfd/mediatek,mt6370.example.dtb:0:0: 
/example-0/i2c/mt6370@34/charger: failed to match any schema with compatible: 
['mediatek,mt6370-charger']
Documentation/devicetree/bindings/mfd/mediatek,mt6370.example.dtb:0:0: 
/example-0/i2c/mt6370@34/indicator: failed to match any schema with compatible: 
['mediatek,mt6370-indicator']
Documentation/devicetree/bindings/mfd/mediatek,mt6370.example.dtb:0:0: 
/example-0/i2c/mt6370@34/flashlight: failed to match any schema with 
compatible: ['mediatek,mt6370-flashlight']
Documentation/devicetree/bindings/mfd/mediatek,mt6370.example.dtb:0:0: 
/example-0/i2c/mt6370@34/tcpc: failed to match any schema with compatible: 
['mediatek,mt6370-tcpc']

doc reference errors (make refcheckdocs):

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

This check can fail if there are 

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

2022-05-31 Thread Rob Herring
On Tue, 31 May 2022 19:18:50 +0800, ChiaEn Wu wrote:
> 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
> 

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:
./Documentation/devicetree/bindings/leds/mediatek,mt6370-flashlight.yaml: $id: 
relative path/filename doesn't match actual path or filename
expected: 
http://devicetree.org/schemas/leds/mediatek,mt6370-flashlight.yaml#

doc reference errors (make refcheckdocs):
Warning: Documentation/devicetree/bindings/leds/mediatek,mt6370-flashlight.yaml 
references a file that doesn't exist: 
Documentation/devicetree/bindings/mfd/mt6370.yaml
Documentation/devicetree/bindings/leds/mediatek,mt6370-flashlight.yaml: 
Documentation/devicetree/bindings/mfd/mt6370.yaml

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: [RESEND 03/14] dt-bindings: leds: mt6370: Add Mediatek mt6370 indicator

2022-05-31 Thread Rob Herring
On Tue, 31 May 2022 19:18:49 +0800, ChiaEn Wu wrote:
> 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
> 

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:


doc reference errors (make refcheckdocs):
Warning: Documentation/devicetree/bindings/leds/mediatek,mt6370-indicator.yaml 
references a file that doesn't exist: 
Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml
Documentation/devicetree/bindings/leds/mediatek,mt6370-indicator.yaml: 
Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml

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: Per file OOM badness

2022-05-31 Thread Alex Deucher
+ dri-devel

On Tue, May 31, 2022 at 6:00 AM Christian König
 wrote:
>
> Hello everyone,
>
> To summarize the issue I'm trying to address here: Processes can allocate
> resources through a file descriptor without being held responsible for it.
>
> Especially for the DRM graphics driver subsystem this is rather
> problematic. Modern games tend to allocate huge amounts of system memory
> through the DRM drivers to make it accessible to GPU rendering.
>
> But even outside of the DRM subsystem this problem exists and it is
> trivial to exploit. See the following simple example of
> using memfd_create():
>
>  fd = memfd_create("test", 0);
>  while (1)
>  write(fd, page, 4096);
>
> Compile this and you can bring down any standard desktop system within
> seconds.
>
> The background is that the OOM killer will kill every processes in the
> system, but just not the one which holds the only reference to the memory
> allocated by the memfd.
>
> Those problems where brought up on the mailing list multiple times now
> [1][2][3], but without any final conclusion how to address them. Since
> file descriptors are considered shared the process can not directly held
> accountable for allocations made through them. Additional to that file
> descriptors can also easily move between processes as well.
>
> So what this patch set does is to instead of trying to account the
> allocated memory to a specific process it adds a callback to struct
> file_operations which the OOM killer can use to query the specific OOM
> badness of this file reference. This badness is then divided by the
> file_count, so that every process using a shmem file, DMA-buf or DRM
> driver will get it's equal amount of OOM badness.
>
> Callbacks are then implemented for the two core users (memfd and DMA-buf)
> as well as 72 DRM based graphics drivers.
>
> The result is that the OOM killer can now much better judge if a process
> is worth killing to free up memory. Resulting a quite a bit better system
> stability in OOM situations, especially while running games.
>
> The only other possibility I can see would be to change the accounting of
> resources whenever references to the file structure change, but this would
> mean quite some additional overhead for a rather common operation.
>
> Additionally I think trying to limit device driver allocations using
> cgroups is orthogonal to this effort. While cgroups is very useful, it
> works on per process limits and tries to enforce a collaborative model on
> memory management while the OOM killer enforces a competitive model.
>
> Please comment and/or review, we have that problem flying around for years
> now and are not at a point where we finally need to find a solution for
> this.
>
> Regards,
> Christian.
>
> [1] 
> https://lists.freedesktop.org/archives/dri-devel/2015-September/089778.html
> [2] https://lkml.org/lkml/2018/1/18/543
> [3] https://lkml.org/lkml/2021/2/4/799
>
>


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

2022-05-31 Thread Abhinav Kumar




On 5/31/2022 5:18 AM, Dmitry Baryshkov wrote:

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_REV0x0
  #define HW_INTR_STATUS0x0010
  
+#define UBWC_DEC_HW_VERSION		0x58

  #define UBWC_STATIC   0x144
  #define UBWC_CTRL_2   0x150
  #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);
+   }
+}
+


Is it possible to unify the above functions by having the internal 
ubwc_version checks?


It seems like msm_mdss_setup_ubwc_dec_xxx can keep growing.

I have not looked into each bit programming but from the top level so 
feel free to correct if wrong but it seems both do write UBWC_STATIC 
(different values based on different UBWC versions) and write some extra 
registers based on version



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


we are already printing the HW version here

https://gitlab.freedesktop.org/drm/msm/-/blob/msm-next/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c#L1096

Do you want to remove that print then?


+
/*
 * 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, 

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

2022-05-31 Thread Doug Anderson
Hi,

On Tue, May 31, 2022 at 2:29 PM Abhinav Kumar  wrote:
>
> > @@ -136,6 +178,13 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss)
> >   {
> >   int ret;
> >
> > + /*
> > +  * Several components have AXI clocks that can only be turned on if
> > +  * the interconnect is enabled (non-zero bandwidth). Let's make sure
> > +  * that the interconnects are at least at a minimum amount.
> > +  */
> > + msm_mdss_icc_request_bw(msm_mdss, MIN_IB_BW);
> > +
>
> This patch does two things :
>
> 1) Move the min icc vote from the dpu_runtime_resume() path to the
> msm_mdss_enable() so that while resuming, we add the min vote to the
> parent device. We do need a min vote before turning on the AXI clk as
> per this comment mentioned in c33b7c0389e1 (drm/msm/dpu: add support for
> clk and bw scaling for display)
>
>
> @@ -1101,8 +1129,15 @@ static int __maybe_unused
> dpu_runtime_resume(struct device *dev)
>  struct drm_encoder *encoder;
>  struct drm_device *ddev;
>  struct dss_module_power *mp = _kms->mp;
> +   int i;
>
>  ddev = dpu_kms->dev;
> +
> +   /* Min vote of BW is required before turning on AXI clk */
> +   for (i = 0; i < dpu_kms->num_paths; i++)
> +   icc_set_bw(dpu_kms->path[i], 0,
> +   dpu_kms->catalog->perf.min_dram_ib);
>
> So I understand and I am fine with this part.
>
> 2) Add a min vote in msm_mdss_init().
>
> This is the part I am not able to fully follow.
>
> If we only need to add the min vote before voting for the clocks, adding
> it in mdss_mdss_enable() should be enough.
>
> Do we need this part of adding the min vote to the msm_mdss_init()?
>
> If so, why?

Ah, good question. Mostly I was matching how things were done before
commit a670ff578f1f ("drm/msm/dpu: always use mdp device to scale
bandwidth"). Before that commit we used to put the min vote in the
init path.

...but you're right, I don't see any good reason for it. I'll send a
v2 removing that line from msm_mdss_init().

-Doug


Re: [Intel-gfx] [PATCH 2/2] drm/i915/pvc: Add initial PVC workarounds

2022-05-31 Thread Matt Atwood
On Fri, May 27, 2022 at 09:33:48AM -0700, Matt Roper wrote:
> From: Stuart Summers 
> 
> Bspec: 64027
Reviewed-by: Matt Atwood 
> Signed-off-by: Stuart Summers 
> Signed-off-by: Matt Roper 
> ---
>  drivers/gpu/drm/i915/gt/intel_engine_regs.h |  5 +-
>  drivers/gpu/drm/i915/gt/intel_gt_regs.h |  3 +-
>  drivers/gpu/drm/i915/gt/intel_workarounds.c | 61 ++---
>  drivers/gpu/drm/i915/intel_pm.c | 16 +-
>  4 files changed, 73 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_engine_regs.h 
> b/drivers/gpu/drm/i915/gt/intel_engine_regs.h
> index 75a0c55c5aa5..44de10cf7837 100644
> --- a/drivers/gpu/drm/i915/gt/intel_engine_regs.h
> +++ b/drivers/gpu/drm/i915/gt/intel_engine_regs.h
> @@ -196,6 +196,7 @@
>  #define RING_CTX_TIMESTAMP(base) _MMIO((base) + 0x3a8) /* gen8+ 
> */
>  #define RING_PREDICATE_RESULT(base)  _MMIO((base) + 0x3b8)
>  #define RING_FORCE_TO_NONPRIV(base, i)   _MMIO(((base) + 0x4D0) 
> + (i) * 4)
> +#define   RING_FORCE_TO_NONPRIV_DENY REG_BIT(30)
>  #define   RING_FORCE_TO_NONPRIV_ADDRESS_MASK REG_GENMASK(25, 2)
>  #define   RING_FORCE_TO_NONPRIV_ACCESS_RW(0 << 28)/* CFL+ & Gen11+ */
>  #define   RING_FORCE_TO_NONPRIV_ACCESS_RD(1 << 28)
> @@ -208,7 +209,9 @@
>  #define   RING_FORCE_TO_NONPRIV_RANGE_64 (3 << 0)
>  #define   RING_FORCE_TO_NONPRIV_RANGE_MASK   (3 << 0)
>  #define   RING_FORCE_TO_NONPRIV_MASK_VALID   \
> - (RING_FORCE_TO_NONPRIV_RANGE_MASK | RING_FORCE_TO_NONPRIV_ACCESS_MASK)
> + (RING_FORCE_TO_NONPRIV_RANGE_MASK | \
> +  RING_FORCE_TO_NONPRIV_ACCESS_MASK | \
> +  RING_FORCE_TO_NONPRIV_DENY)
>  #define   RING_MAX_NONPRIV_SLOTS  12
>  
>  #define RING_EXECLIST_SQ_CONTENTS(base)  _MMIO((base) + 0x510)
> diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h 
> b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
> index b4642dcc192f..58e9b464d564 100644
> --- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h
> +++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
> @@ -1070,8 +1070,9 @@
>  
>  #define GEN10_CACHE_MODE_SS  _MMIO(0xe420)
>  #define   ENABLE_EU_COUNT_FOR_TDL_FLUSH  REG_BIT(10)
> -#define   ENABLE_PREFETCH_INTO_ICREG_BIT(3)
> +#define   DISABLE_ECCREG_BIT(5)
>  #define   FLOAT_BLEND_OPTIMIZATION_ENABLEREG_BIT(4)
> +#define   ENABLE_PREFETCH_INTO_ICREG_BIT(3)
>  
>  #define EU_PERF_CNTL0_MMIO(0xe458)
>  #define EU_PERF_CNTL4_MMIO(0xe45c)
> diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c 
> b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> index 73b59ea6fd3b..a604bc7c0701 100644
> --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
> +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> @@ -776,7 +776,9 @@ __intel_engine_init_ctx_wa(struct intel_engine_cs *engine,
>   if (engine->class != RENDER_CLASS)
>   goto done;
>  
> - if (IS_DG2(i915))
> + if (IS_PONTEVECCHIO(i915))
> + ; /* noop; none at this time */
> + else if (IS_DG2(i915))
>   dg2_ctx_workarounds_init(engine, wal);
>   else if (IS_XEHPSDV(i915))
>   ; /* noop; none at this time */
> @@ -1494,7 +1496,9 @@ gt_init_workarounds(struct intel_gt *gt, struct 
> i915_wa_list *wal)
>  {
>   struct drm_i915_private *i915 = gt->i915;
>  
> - if (IS_DG2(i915))
> + if (IS_PONTEVECCHIO(i915))
> + ; /* none yet */
> + else if (IS_DG2(i915))
>   dg2_gt_workarounds_init(gt, wal);
>   else if (IS_XEHPSDV(i915))
>   xehpsdv_gt_workarounds_init(gt, wal);
> @@ -1924,6 +1928,32 @@ static void dg2_whitelist_build(struct intel_engine_cs 
> *engine)
>   }
>  }
>  
> +static void blacklist_trtt(struct intel_engine_cs *engine)
> +{
> + struct i915_wa_list *w = >whitelist;
> +
> + /*
> +  * Prevent read/write access to [0x4400, 0x4600) which covers
> +  * the TRTT range across all engines. Note that normally userspace
> +  * cannot access the other engines' trtt control, but for simplicity
> +  * we cover the entire range on each engine.
> +  */
> + whitelist_reg_ext(w, _MMIO(0x4400),
> +   RING_FORCE_TO_NONPRIV_DENY |
> +   RING_FORCE_TO_NONPRIV_RANGE_64);
> + whitelist_reg_ext(w, _MMIO(0x4500),
> +   RING_FORCE_TO_NONPRIV_DENY |
> +   RING_FORCE_TO_NONPRIV_RANGE_64);
> +}
> +
> +static void pvc_whitelist_build(struct intel_engine_cs *engine)
> +{
> + allow_read_ctx_timestamp(engine);
> +
> + /* Wa_16014440446:pvc */
> + blacklist_trtt(engine);
> +}
> +
>  void intel_engine_init_whitelist(struct intel_engine_cs *engine)
>  {
>   struct drm_i915_private *i915 = engine->i915;
> @@ -1931,7 +1961,9 @@ void intel_engine_init_whitelist(struct intel_engine_cs 
> *engine)
>  
>   wa_init_start(w, "whitelist", 

Re: [Intel-gfx] [PATCH 1/2] drm/i915/pvc: Extract stepping information from PCI revid

2022-05-31 Thread Matt Atwood
On Fri, May 27, 2022 at 09:33:47AM -0700, Matt Roper wrote:
> For PVC, the base die and compute tile have separate stepping values
> that we need to track; we'll use the existing graphics_step field to
> represent the compute tile stepping and add a new 'basedie_step' field.
> 
> Unlike past platforms, steppings for these components are represented by
> specific bitfields within the PCI revision ID, and we shouldn't make
> assumptions about the non-CT, non-BD bits staying 0.  Let's update our
> stepping code accordingly.
> 
> Bspec: 44484
Reviewed-by: Matt Atwood 
> Signed-off-by: Matt Roper 
> ---
>  drivers/gpu/drm/i915/i915_drv.h   | 13 ++
>  drivers/gpu/drm/i915/intel_step.c | 70 ++-
>  drivers/gpu/drm/i915/intel_step.h |  4 +-
>  3 files changed, 85 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 74b3caccd839..ec1b3484fdaf 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -943,6 +943,7 @@ static inline struct intel_gt *to_gt(struct 
> drm_i915_private *i915)
>  #define INTEL_DISPLAY_STEP(__i915) (RUNTIME_INFO(__i915)->step.display_step)
>  #define INTEL_GRAPHICS_STEP(__i915) 
> (RUNTIME_INFO(__i915)->step.graphics_step)
>  #define INTEL_MEDIA_STEP(__i915) (RUNTIME_INFO(__i915)->step.media_step)
> +#define INTEL_BASEDIE_STEP(__i915) (RUNTIME_INFO(__i915)->step.basedie_step)
>  
>  #define IS_DISPLAY_STEP(__i915, since, until) \
>   (drm_WARN_ON(&(__i915)->drm, INTEL_DISPLAY_STEP(__i915) == STEP_NONE), \
> @@ -956,6 +957,10 @@ static inline struct intel_gt *to_gt(struct 
> drm_i915_private *i915)
>   (drm_WARN_ON(&(__i915)->drm, INTEL_MEDIA_STEP(__i915) == STEP_NONE), \
>INTEL_MEDIA_STEP(__i915) >= (since) && INTEL_MEDIA_STEP(__i915) < 
> (until))
>  
> +#define IS_BASEDIE_STEP(__i915, since, until) \
> + (drm_WARN_ON(&(__i915)->drm, INTEL_BASEDIE_STEP(__i915) == STEP_NONE), \
> +  INTEL_BASEDIE_STEP(__i915) >= (since) && INTEL_BASEDIE_STEP(__i915) < 
> (until))
> +
>  static __always_inline unsigned int
>  __platform_mask_index(const struct intel_runtime_info *info,
> enum intel_platform p)
> @@ -1208,6 +1213,14 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
>   (IS_DG2(__i915) && \
>IS_DISPLAY_STEP(__i915, since, until))
>  
> +#define IS_PVC_BD_STEP(__i915, since, until) \
> + (IS_PONTEVECCHIO(__i915) && \
> +  IS_BASEDIE_STEP(__i915, since, until))
> +
> +#define IS_PVC_CT_STEP(__i915, since, until) \
> + (IS_PONTEVECCHIO(__i915) && \
> +  IS_GRAPHICS_STEP(__i915, since, until))
> +
>  #define IS_LP(dev_priv)  (INTEL_INFO(dev_priv)->is_lp)
>  #define IS_GEN9_LP(dev_priv) (GRAPHICS_VER(dev_priv) == 9 && IS_LP(dev_priv))
>  #define IS_GEN9_BC(dev_priv) (GRAPHICS_VER(dev_priv) == 9 && 
> !IS_LP(dev_priv))
> diff --git a/drivers/gpu/drm/i915/intel_step.c 
> b/drivers/gpu/drm/i915/intel_step.c
> index 74e8e4680028..42b3133d8387 100644
> --- a/drivers/gpu/drm/i915/intel_step.c
> +++ b/drivers/gpu/drm/i915/intel_step.c
> @@ -135,6 +135,8 @@ static const struct intel_step_info adlp_n_revids[] = {
>   [0x0] = { COMMON_GT_MEDIA_STEP(A0), .display_step = STEP_D0 },
>  };
>  
> +static void pvc_step_init(struct drm_i915_private *i915, int pci_revid);
> +
>  void intel_step_init(struct drm_i915_private *i915)
>  {
>   const struct intel_step_info *revids = NULL;
> @@ -142,7 +144,10 @@ void intel_step_init(struct drm_i915_private *i915)
>   int revid = INTEL_REVID(i915);
>   struct intel_step_info step = {};
>  
> - if (IS_DG2_G10(i915)) {
> + if (IS_PONTEVECCHIO(i915)) {
> + pvc_step_init(i915, revid);
> + return;
> + } else if (IS_DG2_G10(i915)) {
>   revids = dg2_g10_revid_step_tbl;
>   size = ARRAY_SIZE(dg2_g10_revid_step_tbl);
>   } else if (IS_DG2_G11(i915)) {
> @@ -235,6 +240,69 @@ void intel_step_init(struct drm_i915_private *i915)
>   RUNTIME_INFO(i915)->step = step;
>  }
>  
> +#define PVC_BD_REVID GENMASK(5, 3)
> +#define PVC_CT_REVID GENMASK(2, 0)
> +
> +static const int pvc_bd_subids[] = {
> + [0x0] = STEP_A0,
> + [0x3] = STEP_B0,
> + [0x4] = STEP_B1,
> + [0x5] = STEP_B3,
> +};
> +
> +static const int pvc_ct_subids[] = {
> + [0x3] = STEP_A0,
> + [0x5] = STEP_B0,
> + [0x6] = STEP_B1,
> + [0x7] = STEP_C0,
> +};
> +
> +static int
> +pvc_step_lookup(struct drm_i915_private *i915, const char *type,
> + const int *table, int size, int subid)
> +{
> + if (subid < size && table[subid] != STEP_NONE)
> + return table[subid];
> +
> + drm_warn(>drm, "Unknown %s id 0x%02x\n", type, subid);
> +
> + /*
> +  * As on other platforms, try to use the next higher ID if we land on a
> +  * gap in the table.
> +  */
> + while (subid < size && table[subid] == STEP_NONE)
> + subid++;
> +
> + if (subid < 

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

2022-05-31 Thread Abhinav Kumar

Hi Doug

On 5/31/2022 7:28 AM, Douglas Anderson wrote:

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 

Re: [PATCH] drm/amdgpu: make gfx_v11_0_rlc_stop static

2022-05-31 Thread Alex Deucher
Applied.  Thanks!

Alex

On Sun, May 29, 2022 at 7:50 AM sunliming  wrote:
>
> This symbol is not used outside of gfx_v11_0.c, so marks it static.
>
> Fixes the following w1 warning:
>
> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c:1945:6: warning: no previous
> prototype for function 'gfx_v11_0_rlc_stop' [-Wmissing-prototypes].
>
> Reported-by: kernel test robot 
> Signed-off-by: sunliming 
> ---
>  drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c 
> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> index 8c0a3fc7aaa6..cb581cfc7464 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> @@ -1983,7 +1983,7 @@ static int gfx_v11_0_init_csb(struct amdgpu_device 
> *adev)
> return 0;
>  }
>
> -void gfx_v11_0_rlc_stop(struct amdgpu_device *adev)
> +static void gfx_v11_0_rlc_stop(struct amdgpu_device *adev)
>  {
> u32 tmp = RREG32_SOC15(GC, 0, regRLC_CNTL);
>
> --
> 2.25.1
>


Re: [PATCH] drm/amdgpu: fix a missing break in gfx_v11_0_handle_priv_fault

2022-05-31 Thread Alex Deucher
Applied.  Thanks!

On Sun, May 29, 2022 at 7:50 AM sunliming  wrote:
>
> Fixes the following w1 warning:
>
> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c:5873:2: warning: unannotated
> fall-through between switch labels [-Wimplicit-fallthrough].
>
> Reported-by: kernel test robot 
> Signed-off-by: sunliming 
> ---
>  drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c 
> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> index cb581cfc7464..628d3536938e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> @@ -6028,6 +6028,7 @@ static void gfx_v11_0_handle_priv_fault(struct 
> amdgpu_device *adev,
> break;
> default:
> BUG();
> +   break;
> }
>  }
>
> --
> 2.25.1
>


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

2022-05-31 Thread Dmitry Baryshkov
On Tue, 31 May 2022 at 23:37, Rob Clark  wrote:
>
> On Tue, May 31, 2022 at 1:34 PM Dmitry Baryshkov
>  wrote:
> >
> > On Tue, 31 May 2022 at 23:08, Rob Clark  wrote:
> > >
> > > 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().
> > >
> > > Fixes: e5516553999f ("drm: call drm_gem_object_funcs.mmap with fake 
> > > offset")
> > > Signed-off-by: Rob Clark 
> > > ---
> > >  drivers/gpu/drm/msm/msm_drv.c   |  2 +-
> > >  drivers/gpu/drm/msm/msm_drv.h   |  1 +
> > >  drivers/gpu/drm/msm/msm_gem_prime.c | 15 +++
> > >  3 files changed, 17 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> > > index 44485363f37a..14ab9a627d8b 100644
> > > --- a/drivers/gpu/drm/msm/msm_drv.c
> > > +++ b/drivers/gpu/drm/msm/msm_drv.c
> > > @@ -964,7 +964,7 @@ static const struct drm_driver msm_driver = {
> > > .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> > > .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> > > .gem_prime_import_sg_table = msm_gem_prime_import_sg_table,
> > > -   .gem_prime_mmap = drm_gem_prime_mmap,
> > > +   .gem_prime_mmap = msm_gem_prime_mmap,
> > >  #ifdef CONFIG_DEBUG_FS
> > > .debugfs_init   = msm_debugfs_init,
> > >  #endif
> > > diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> > > index bb052071b16d..090b8074fec7 100644
> > > --- a/drivers/gpu/drm/msm/msm_drv.h
> > > +++ b/drivers/gpu/drm/msm/msm_drv.h
> > > @@ -275,6 +275,7 @@ unsigned long msm_gem_shrinker_shrink(struct 
> > > drm_device *dev, unsigned long nr_t
> > >  void msm_gem_shrinker_init(struct drm_device *dev);
> > >  void msm_gem_shrinker_cleanup(struct drm_device *dev);
> > >
> > > +int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct 
> > > *vma);
> > >  struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj);
> > >  int msm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map 
> > > *map);
> > >  void msm_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map 
> > > *map);
> > > diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c 
> > > b/drivers/gpu/drm/msm/msm_gem_prime.c
> > > index 94ab705e9b8a..dcc8a573bc76 100644
> > > --- a/drivers/gpu/drm/msm/msm_gem_prime.c
> > > +++ b/drivers/gpu/drm/msm/msm_gem_prime.c
> > > @@ -11,6 +11,21 @@
> > >  #include "msm_drv.h"
> > >  #include "msm_gem.h"
> > >
> > > +int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct 
> > > *vma)
> > > +{
> > > +   int ret;
> > > +
> > > +   /* Ensure the mmap offset is initialized.  We lazily initialize 
> > > it,
> > > +* so if it has not been first mmap'd directly as a GEM object, 
> > > the
> > > +* mmap offset will not be already initialized.
> > > +*/
> > > +   ret = drm_gem_create_mmap_offset(obj);
> > > +   if (ret)
> > > +   return ret;
> >
> > Wouldn't it be better to have this call directly in the
> > drm_gem_prime_mmap() ? This way all drivers can be lazy.
> >
>
> yes.. that was my first[1] proposal.  But there are differences of
> opinion, and in the mean time I want to get this particular issue
> fixed ;-)

Ack, excuse me, I probably skipped the thread.

Reviewed-by: Dmitry Baryshkov 

>
> BR,
> -R
>
> [1] https://patchwork.freedesktop.org/patch/487597/
>
> >
> > > +
> > > +   return drm_gem_prime_mmap(obj, vma);
> > > +}
> > > +
> > >  struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj)
> > >  {
> > > struct msm_gem_object *msm_obj = to_msm_bo(obj);
> > > --
> > > 2.36.1
> > >
> >
> >
> > --
> > With best wishes
> > Dmitry



-- 
With best wishes
Dmitry


Re: [PATCH v3 3/4] drm/bridge: Add devm_drm_bridge_add()

2022-05-31 Thread Doug Anderson
Maxime,

On Mon, May 23, 2022 at 10:00 AM Doug Anderson  wrote:
>
> Hi,
>
> On Sat, May 21, 2022 at 2:17 AM Maxime Ripard  wrote:
> >
> > Hi,
> >
> > On Tue, May 10, 2022 at 12:29:43PM -0700, Douglas Anderson wrote:
> > > This adds a devm managed version of drm_bridge_add(). Like other
> > > "devm" function listed in drm_bridge.h, this function takes an
> > > explicit "dev" to use for the lifetime management. A few notes:
> > > * In general we have a "struct device" for bridges that makes a good
> > >   candidate for where the lifetime matches exactly what we want.
> > > * The "bridge->dev->dev" device appears to be the encoder
> > >   device. That's not the right device to use for lifetime management.
> > >
> > > Suggested-by: Dmitry Baryshkov 
> > > Signed-off-by: Douglas Anderson 
> >
> > If we are to introduce more managed helpers, I think it'd be wiser to
> > introduce them as DRM-managed, and not device managed.
> >
> > Otherwise, you'll end up in a weird state when a device has been removed
> > but the DRM device is still around.
>
> I'm kinda confused. In this case there is no DRM device for the bridge
> and, as per my CL description, "bridge-dev->dev" appears to be the
> encoder device. I wasn't personally involved in discussions about it,
> but I was under the impression that this was expected / normal. Thus
> we can't make this DRM-managed.

Since I didn't hear a reply, I'll assume that my response addressed
your concerns. Assuming I get reviews for the other two patches in
this series I'll plan to land this with Dmitry's review.

-Doug


Re: [PATCH v3 0/4] drm/dp: Make DP AUX bus usage easier; use it on ps8640

2022-05-31 Thread Doug Anderson
Hi,

On Tue, May 10, 2022 at 12:30 PM Douglas Anderson  wrote:
>
> This patch is v3 of the first 2 patches from my RFC series ("drm/dp: 
> Improvements
> for DP AUX channel") [1]. I've broken the series in two so we can make
> progress on the two halves separately.
>
> v2 of this series tries to incorporate all the feedback from v1. Hopefully
> things are less confusing and simpler this time around. The one thing that got
> slightly more confusing is that the done_probing() callback can't return
> -EPROBE_DEFER in most cases so we have to adjust drivers a little more.
>
> v3 takes Dmitry's advice on v2. This now introduces
> devm_drm_bridge_add() (in an extra patch), splits some fixups into
> their own patch, uses a new name for functions, and requires an
> explicit call to done_probing if you have no children.
>
> The idea for this series came up during the review process of
> Sankeerth's series trying to add eDP for Qualcomm SoCs [2].
>
> This _doesn't_ attempt to fix the Analogix driver. If this works out,
> ideally someone can post a patch up to do that.
>
> NOTE: I don't have any ps8640 devices that _don't_ use the aux panel
> underneath them, so I'm relying on code inspection to make sure I
> didn't break those. If someone sees that I did something wrong for
> that case then please yell!
>
> [1] https://lore.kernel.org/r/20220409023628.2104952-1-diand...@chromium.org/
> [2] 
> https://lore.kernel.org/r/1648656179-10347-2-git-send-email-quic_sbill...@quicinc.com/
>
> Changes in v3:
> - Adapt to v3 changes in aux bus.
> - Don't call done_probing() if there are no children; return -ENODEV.
> - Patch ("drm/bridge: Add devm_drm_bridge_add()") new for v3.
> - Patch ("drm/dp: Export symbol / kerneldoc fixes...") split for v3.
> - Split out EXPORT_SYMBOL and kerneldoc fixes to its own patch.
> - Use devm_drm_bridge_add() to simplify.
> - Used Dmitry's proposed name: of_dp_aux_populate_bus()
>
> Changes in v2:
> - Change to assume exactly one device.
> - Have a probe callback instead of an extra sub device.
> - Rewrote atop new method introduced by patch #1.
>
> Douglas Anderson (4):
>   drm/dp: Export symbol / kerneldoc fixes for DP AUX bus
>   drm/dp: Add callbacks to make using DP AUX bus properly easier
>   drm/bridge: Add devm_drm_bridge_add()
>   drm/bridge: parade-ps8640: Handle DP AUX more properly
>
>  drivers/gpu/drm/bridge/parade-ps8640.c   |  74 +---
>  drivers/gpu/drm/display/drm_dp_aux_bus.c | 211 +++
>  drivers/gpu/drm/drm_bridge.c |  23 +++
>  include/drm/display/drm_dp_aux_bus.h |  34 +++-
>  include/drm/drm_bridge.h |   1 +
>  5 files changed, 238 insertions(+), 105 deletions(-)

I'm hoping to get some review for this series. Anyone? Dmitry: I know
you looked at earlier versions of this series. I guess you're happy
enough with it now but don't feel enough ownership to give a full
Reviewed-by?

-Doug


Re: [PATCH 14/14] dt-bindings: mfd: Add Mediatek MT6370 binding documentation

2022-05-31 Thread Krzysztof Kozlowski
On 31/05/2022 12:28, ChiaEn Wu wrote:
> From: ChiYuan Huang 
> 
> Add Mediatek MT6370 binding documentation.

Subject: same as previous patches.

> 
> 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.

This sentence does not make any sense. The "description" field is to
describe, explain the meaning behind given property.

> +
> +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

Ditto

> +
> +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

Same comment as your patch #10.

> +
> +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 {

Generic node name, so "pmic".

> +compatible = "mediatek,mt6370";
> +reg = <0x34>;
> +wakeup-source;
> +interrupts-extended = < 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 = <_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>;
> +

Re: [PATCH 12/14] dt-bindings: leds: Add Mediatek MT6370 flashlight binding documentation

2022-05-31 Thread Krzysztof Kozlowski
On 31/05/2022 12:42, ChiaEn Wu wrote:
> From: Alice Chen 
> 

Subject - same comment as previous #10 patch.

> 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.

Same as patch #11.

> +
> +properties:
> +  reg:
> +description: Index of the flash LED.

As well.

> +enum:
> +  - 0 #Address of LED1
> +  - 1 #Address of LED2

'#' starts a comment, so there is always a space after '#'

> +
> +unevaluatedProperties: false
> +
> +required:
> +  - compatible
> +  - "#address-cells"
> +  - "#size-cells"
> +
> +additionalProperties: false


Best regards,
Krzysztof


Re: [PATCH 11/14] dt-bindings: leds: mt6370: Add Mediatek mt6370 indicator documentation

2022-05-31 Thread Krzysztof Kozlowski
On 31/05/2022 12:42, ChiaEn Wu wrote:
> 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.

Not useful description. Just skip it, I think schema allows it.

> +$ref: common.yaml#
> +type: object
> +
> +properties:
> +  reg:
> +description: |
> +  Index of the LED.

The same, regs are usually not described.

> +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.

Why here you start sentence lower-case?

> +$ref: /schemas/types.yaml#/definitions/uint32
> +enum: [0, 1, 2, 3]

This has to be in logical values, so in ms, not in some register values.
Use proper unit suffix and enumerate the actual values.

> +
> +unevaluatedProperties: false
> +
> +required:
> +  - compatible
> +  - "#address-cells"
> +  - "#size-cells"
> +
> +additionalProperties: false


Best regards,
Krzysztof


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

2022-05-31 Thread Rob Clark
On Tue, May 31, 2022 at 1:34 PM Dmitry Baryshkov
 wrote:
>
> On Tue, 31 May 2022 at 23:08, Rob Clark  wrote:
> >
> > 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().
> >
> > Fixes: e5516553999f ("drm: call drm_gem_object_funcs.mmap with fake offset")
> > Signed-off-by: Rob Clark 
> > ---
> >  drivers/gpu/drm/msm/msm_drv.c   |  2 +-
> >  drivers/gpu/drm/msm/msm_drv.h   |  1 +
> >  drivers/gpu/drm/msm/msm_gem_prime.c | 15 +++
> >  3 files changed, 17 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> > index 44485363f37a..14ab9a627d8b 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.c
> > +++ b/drivers/gpu/drm/msm/msm_drv.c
> > @@ -964,7 +964,7 @@ static const struct drm_driver msm_driver = {
> > .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> > .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> > .gem_prime_import_sg_table = msm_gem_prime_import_sg_table,
> > -   .gem_prime_mmap = drm_gem_prime_mmap,
> > +   .gem_prime_mmap = msm_gem_prime_mmap,
> >  #ifdef CONFIG_DEBUG_FS
> > .debugfs_init   = msm_debugfs_init,
> >  #endif
> > diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> > index bb052071b16d..090b8074fec7 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.h
> > +++ b/drivers/gpu/drm/msm/msm_drv.h
> > @@ -275,6 +275,7 @@ unsigned long msm_gem_shrinker_shrink(struct drm_device 
> > *dev, unsigned long nr_t
> >  void msm_gem_shrinker_init(struct drm_device *dev);
> >  void msm_gem_shrinker_cleanup(struct drm_device *dev);
> >
> > +int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct 
> > *vma);
> >  struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj);
> >  int msm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map);
> >  void msm_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map 
> > *map);
> > diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c 
> > b/drivers/gpu/drm/msm/msm_gem_prime.c
> > index 94ab705e9b8a..dcc8a573bc76 100644
> > --- a/drivers/gpu/drm/msm/msm_gem_prime.c
> > +++ b/drivers/gpu/drm/msm/msm_gem_prime.c
> > @@ -11,6 +11,21 @@
> >  #include "msm_drv.h"
> >  #include "msm_gem.h"
> >
> > +int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct 
> > *vma)
> > +{
> > +   int ret;
> > +
> > +   /* Ensure the mmap offset is initialized.  We lazily initialize it,
> > +* so if it has not been first mmap'd directly as a GEM object, the
> > +* mmap offset will not be already initialized.
> > +*/
> > +   ret = drm_gem_create_mmap_offset(obj);
> > +   if (ret)
> > +   return ret;
>
> Wouldn't it be better to have this call directly in the
> drm_gem_prime_mmap() ? This way all drivers can be lazy.
>

yes.. that was my first[1] proposal.  But there are differences of
opinion, and in the mean time I want to get this particular issue
fixed ;-)

BR,
-R

[1] https://patchwork.freedesktop.org/patch/487597/

>
> > +
> > +   return drm_gem_prime_mmap(obj, vma);
> > +}
> > +
> >  struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj)
> >  {
> > struct msm_gem_object *msm_obj = to_msm_bo(obj);
> > --
> > 2.36.1
> >
>
>
> --
> With best wishes
> Dmitry


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

2022-05-31 Thread Rob Clark
On Mon, May 30, 2022 at 12:34 AM Haowen Bai  wrote:
>
> The ctx->hw is dereferencing before null checking, so move
> it after checking.
>
> Signed-off-by: Haowen Bai 
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c 
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
> index be292937..e59680cdd0ce 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
> @@ -155,11 +155,13 @@ static void dpu_hw_wb_roi(struct dpu_hw_wb *ctx, struct 
> dpu_hw_wb_cfg *wb)
>  static void dpu_hw_wb_setup_qos_lut(struct dpu_hw_wb *ctx,
> struct dpu_hw_wb_qos_cfg *cfg)
>  {
> -   struct dpu_hw_blk_reg_map *c = >hw;
> +   struct dpu_hw_blk_reg_map *c;
> u32 qos_ctrl = 0;
>
> if (!ctx || !cfg)
> return;
> +
> +   c = >hw;

tbh, we should just drop both of these null checks.. there is no
codepath that can reach this with potential for either param to be
NULL

BR,
-R

>
> DPU_REG_WRITE(c, WB_DANGER_LUT, cfg->danger_lut);
> DPU_REG_WRITE(c, WB_SAFE_LUT, cfg->safe_lut);
> --
> 2.7.4
>


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

2022-05-31 Thread Dmitry Baryshkov
On Tue, 31 May 2022 at 23:08, Rob Clark  wrote:
>
> 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().
>
> Fixes: e5516553999f ("drm: call drm_gem_object_funcs.mmap with fake offset")
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/msm_drv.c   |  2 +-
>  drivers/gpu/drm/msm/msm_drv.h   |  1 +
>  drivers/gpu/drm/msm/msm_gem_prime.c | 15 +++
>  3 files changed, 17 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index 44485363f37a..14ab9a627d8b 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -964,7 +964,7 @@ static const struct drm_driver msm_driver = {
> .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> .gem_prime_import_sg_table = msm_gem_prime_import_sg_table,
> -   .gem_prime_mmap = drm_gem_prime_mmap,
> +   .gem_prime_mmap = msm_gem_prime_mmap,
>  #ifdef CONFIG_DEBUG_FS
> .debugfs_init   = msm_debugfs_init,
>  #endif
> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index bb052071b16d..090b8074fec7 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -275,6 +275,7 @@ unsigned long msm_gem_shrinker_shrink(struct drm_device 
> *dev, unsigned long nr_t
>  void msm_gem_shrinker_init(struct drm_device *dev);
>  void msm_gem_shrinker_cleanup(struct drm_device *dev);
>
> +int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct 
> *vma);
>  struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj);
>  int msm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map);
>  void msm_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map);
> diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c 
> b/drivers/gpu/drm/msm/msm_gem_prime.c
> index 94ab705e9b8a..dcc8a573bc76 100644
> --- a/drivers/gpu/drm/msm/msm_gem_prime.c
> +++ b/drivers/gpu/drm/msm/msm_gem_prime.c
> @@ -11,6 +11,21 @@
>  #include "msm_drv.h"
>  #include "msm_gem.h"
>
> +int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct 
> *vma)
> +{
> +   int ret;
> +
> +   /* Ensure the mmap offset is initialized.  We lazily initialize it,
> +* so if it has not been first mmap'd directly as a GEM object, the
> +* mmap offset will not be already initialized.
> +*/
> +   ret = drm_gem_create_mmap_offset(obj);
> +   if (ret)
> +   return ret;

Wouldn't it be better to have this call directly in the
drm_gem_prime_mmap() ? This way all drivers can be lazy.


> +
> +   return drm_gem_prime_mmap(obj, vma);
> +}
> +
>  struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj)
>  {
> struct msm_gem_object *msm_obj = to_msm_bo(obj);
> --
> 2.36.1
>


-- 
With best wishes
Dmitry


Re: [PATCH 10/14] dt-bindings: power: supply: Add Mediatek MT6370 Charger binding documentation

2022-05-31 Thread Krzysztof Kozlowski
On 31/05/2022 12:42, ChiaEn Wu wrote:
> From: ChiaEn Wu 
> 

Subject - remove "binding documentation". It's already implied by prefix.

> 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

s/for mt6370 charger//
in each item

> +
> +  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.

Constraints (e.g. maxItems) are needed.

> +
> +  usb-otg-vbus:

Let's keep the same name as in MT6360:

usb-otg-vbus-regulator
> +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

This description is pointless - does not bring any more information. You
repeat the schema. Please, avoid such descriptions.

> +
> +required:
> +  - compatible
> +  - interrupts
> +  - interrupt-names
> +  - io-channels
> +
> +additionalProperties: false


How about example? Or is it going to be in MFD schema?


Best regards,
Krzysztof


[PATCH] drm/msm: Ensure mmap offset is initialized

2022-05-31 Thread 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().

Fixes: e5516553999f ("drm: call drm_gem_object_funcs.mmap with fake offset")
Signed-off-by: Rob Clark 
---
 drivers/gpu/drm/msm/msm_drv.c   |  2 +-
 drivers/gpu/drm/msm/msm_drv.h   |  1 +
 drivers/gpu/drm/msm/msm_gem_prime.c | 15 +++
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 44485363f37a..14ab9a627d8b 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -964,7 +964,7 @@ static const struct drm_driver msm_driver = {
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_import_sg_table = msm_gem_prime_import_sg_table,
-   .gem_prime_mmap = drm_gem_prime_mmap,
+   .gem_prime_mmap = msm_gem_prime_mmap,
 #ifdef CONFIG_DEBUG_FS
.debugfs_init   = msm_debugfs_init,
 #endif
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index bb052071b16d..090b8074fec7 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -275,6 +275,7 @@ unsigned long msm_gem_shrinker_shrink(struct drm_device 
*dev, unsigned long nr_t
 void msm_gem_shrinker_init(struct drm_device *dev);
 void msm_gem_shrinker_cleanup(struct drm_device *dev);
 
+int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
 struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj);
 int msm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map);
 void msm_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map);
diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c 
b/drivers/gpu/drm/msm/msm_gem_prime.c
index 94ab705e9b8a..dcc8a573bc76 100644
--- a/drivers/gpu/drm/msm/msm_gem_prime.c
+++ b/drivers/gpu/drm/msm/msm_gem_prime.c
@@ -11,6 +11,21 @@
 #include "msm_drv.h"
 #include "msm_gem.h"
 
+int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
+{
+   int ret;
+
+   /* Ensure the mmap offset is initialized.  We lazily initialize it,
+* so if it has not been first mmap'd directly as a GEM object, the
+* mmap offset will not be already initialized.
+*/
+   ret = drm_gem_create_mmap_offset(obj);
+   if (ret)
+   return ret;
+
+   return drm_gem_prime_mmap(obj, vma);
+}
+
 struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj)
 {
struct msm_gem_object *msm_obj = to_msm_bo(obj);
-- 
2.36.1



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

2022-05-31 Thread Martin Blumenstingl
Hello,

first of all: thank you for spotting this and sending a patch!

On Tue, May 31, 2022 at 4:49 PM Miaoqian Lin  wrote:
[...]
> 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);
further down in the same function remote is used again:
  pdev = of_find_device_by_node(remote);

My understanding is that we should only use of_node_put() once we
don't need to access the node (in this case the variable is "remote")
anymore.


Best regards,
Martin


[PATCH v5 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 4b547188ec40..3295c8bf6c63 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;
@@ -59,6 +60,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)
 {
@@ -1764,4 +1767,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, )) {
+   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 v5 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 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(>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);

[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(, 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 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, , 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 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(_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 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(_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(_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 = _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(>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(>lock);
 
-   return true;
+   return 0;
 
 err_release:
mutex_unlock(>devmem_lock);
-   release_mem_region(devmem->pagemap.range.start, 
range_len(>pagemap.range));
+   if (res && devmem->pagemap.type == MEMORY_DEVICE_PRIVATE)
+   release_mem_region(devmem->pagemap.range.start,
+  range_len(>pagemap.range));
 err_devmem:
kfree(devmem);
 
-   return false;
+  

[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, _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, _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 = _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 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 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(>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(>page);
+   unpin_user_page(>page);
+   }
+
+   pages[i] = migrate_device_page(>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 = _pfn;
+   args.dst = _pfn;
+   args.cpages = 1;
+   args.npages = 1;
+   args.vma = NULL;
+   migrate_vma_setup();
+   if (!(src_pfn & MIGRATE_PFN_MIGRATE))
+   return NULL;
+
+   dpage = alloc_pages(GFP_USER | __GFP_NOWARN, 0);
+
+   /*
+* get/pin the new 

[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 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 && 

[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(>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(>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;
+   case 

[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  

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 


[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 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(>mutex);
+   cmd->zone_device_type = dmirror->mdevice->zone_device_type;
+   mutex_unlock(>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?


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: [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 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[] = {
> > > > > > +   _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


[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] 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 = _state->mode;
adj_mode = _state->adjusted_mode;
global_state = dpu_kms_get_global_state(crtc_state->state);
if (IS_ERR(global_state))


[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 = < 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 = <_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 = ;
+  };
+  led@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),
+   

[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 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 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 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(>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,
+ _val, sizeof(be_val));
+   if (ret)
+   goto adc_unlock;
+
+   *val = be16_to_cpu(be_val);
+   ret = IIO_VAL_INT;
+
+adc_unlock:
+   mutex_unlock(>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 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 {
+   

[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 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, );
+   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 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(>lock);
+
+   /*

[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,
+   

[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 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, , 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, , sizeof(u16));
+   if (ret)
+   return ret;
+
+   if (vid != MT6370_VENDOR_ID) {
+   dev_err(priv->dev, "Vendor ID not correct 

[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 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



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[] = {
> > > > > +   _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",
> > > > > >kobj);
> > > > > +   if (!dma_buf_caps_kobj)
> > > > > +   return -ENOMEM;
> > > > > +
> > > > > +   ret = sysfs_create_group(dma_buf_caps_kobj,
> > > > > _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



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: 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 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(>mutex);
> + cmd->zone_device_type = dmirror->mdevice->zone_device_type;
> + mutex_unlock(>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: [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: [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 = >mode_config;
> +
> + if (!config->prop_vrr_enabled)
> + return;
> +
> + drm_object_property_set_value(>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: [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: 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


[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=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.

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

[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, , 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 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(_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(_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 = _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(>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(>lock);
 
-   return true;
+   return 0;
 
 err_release:
mutex_unlock(>devmem_lock);
-   release_mem_region(devmem->pagemap.range.start, 
range_len(>pagemap.range));
+   if (res && devmem->pagemap.type == MEMORY_DEVICE_PRIVATE)
+   release_mem_region(devmem->pagemap.range.start,
+  range_len(>pagemap.range));
 err_devmem:
kfree(devmem);
 
-   return false;
+  

[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(, 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 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 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, )) {
+   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 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(>mutex);
+   cmd->zone_device_type = dmirror->mdevice->zone_device_type;
+   mutex_unlock(>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, );
break;
 
+   case HMM_DMIRROR_GET_MEM_DEV_TYPE:
+   ret = dmirror_get_device_type(dmirror, );
+   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(_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 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(>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(>page);
+   unpin_user_page(>page);
+   }
+
+   pages[i] = migrate_device_page(>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 = _pfn;
+   args.dst = _pfn;
+   args.cpages = 1;
+   args.npages = 1;
+   args.vma = NULL;
+   migrate_vma_setup();
+   if (!(src_pfn & MIGRATE_PFN_MIGRATE))
+   return NULL;
+
+   dpage = alloc_pages(GFP_USER | __GFP_NOWARN, 0);
+
+   /*
+* get/pin the new 

[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, _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, _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 = _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 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 ++--
 

[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 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 && 

  1   2   >