Re: [PATCH] drm/amd/display: Enabling eDP no power sequencing with DAL feature mask

2021-06-21 Thread Cornij, Nikola
[Public]



>From: Liu, Zhan 
>Sent: Monday, June 21, 2021 9:13 PM
>To: amd-gfx@lists.freedesktop.org ; Cornij, 
>Nikola 
>Cc: Liu, Charlene 
>Subject: [PATCH] drm/amd/display: Enabling eDP no power sequencing with DAL 
>feature mask
>
>[Public]
>
>[Why]
>Sometimes, DP receiver chip power-controlled externally by an
>Embedded Controller could be treated and used as eDP,
>if it drives mobile display. In this case,
>we shouldn't be doing power-sequencing, hence we can skip
>waiting for T7-ready and T9-ready."
>
>[How]
>Added a feature mask to enable eDP no power sequencing feature.
>
>To enable this, set 0x10 flag in amdgpu.dcfeaturemask on
>Linux command line.
>
>Signed-off-by: Zhan Liu 
Reviewed-by: Nikola Cornij 
>Change-Id: I15e8fb2979fe3ff5491ccf1ee384693d4dce787c
>---
> drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c   |  1 +
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  3 ++
> drivers/gpu/drm/amd/display/dc/dc.h   |  1 +
> .../display/dc/dce110/dce110_hw_sequencer.c   | 31 ---
> drivers/gpu/drm/amd/include/amd_shared.h  | 10 +++---
> 5 files changed, 38 insertions(+), 8 deletions(-)
>
>diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
>b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
>index 3de1accb060e..b588cf4398db 100644
>--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
>+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
>@@ -159,6 +159,7 @@ int amdgpu_smu_pptable_id = -1;
>  * highest. That helps saving some idle power.
>  * DISABLE_FRACTIONAL_PWM (bit 2) disabled by default
>  * PSR (bit 3) disabled by default
>+ * EDP NO POWER SEQUENCING (bit 4) disabled by default
>  */
> uint amdgpu_dc_feature_mask = 2;
> uint amdgpu_dc_debug_mask;
>diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
>b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>index c0a3119982b0..abba26c8f20a 100644
>--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>@@ -1174,6 +1174,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
>if (amdgpu_dc_feature_mask & DC_DISABLE_FRACTIONAL_PWM_MASK)
>init_data.flags.disable_fractional_pwm = true;
>
>+   if (amdgpu_dc_feature_mask & DC_EDP_NO_POWER_SEQUENCING)
>+   init_data.flags.edp_no_power_sequencing = true;
>+
>init_data.flags.power_down_display_on_boot = true;
>
>INIT_LIST_HEAD(>dm.da_list);
>diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
>b/drivers/gpu/drm/amd/display/dc/dc.h
>index a70697898025..7f1d2d6f9de8 100644
>--- a/drivers/gpu/drm/amd/display/dc/dc.h
>+++ b/drivers/gpu/drm/amd/display/dc/dc.h
>@@ -297,6 +297,7 @@ struct dc_config {
>bool allow_seamless_boot_optimization;
>bool power_down_display_on_boot;
>bool edp_not_connected;
>+   bool edp_no_power_sequencing;
>bool force_enum_edp;
>bool forced_clocks;
>bool allow_lttpr_non_transparent_mode;
>diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c 
>b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
>index 53dd305fa6b0..013d94c9506a 100644
>--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
>+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
>@@ -1023,8 +1023,20 @@ void dce110_edp_backlight_control(
>/* dc_service_sleep_in_milliseconds(50); */
>/*edp 1.2*/
>panel_instance = link->panel_cntl->inst;
>-   if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON)
>-   edp_receiver_ready_T7(link);
>+
>+   if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) {
>+   if (!link->dc->config.edp_no_power_sequencing)
>+   /*
>+* Sometimes, DP receiver chip power-controlled externally by 
>an
>+* Embedded Controller could be treated and used as eDP,
>+* if it drives mobile display. In this case,
>+* we shouldn't be doing power-sequencing, hence we can skip
>+* waiting for T7-ready.
>+*/
>+   edp_receiver_ready_T7(link);
>+   else
>+   DC_LOG_DC("edp_receiver_ready_T7 skipped\n");
>+   }
>
>if (ctx->dc->ctx->dmub_srv &&
>ctx->dc->debug.dmub_command_table) {
>@@ -1049,8 +1061,19 @@ void dce110_edp_backlight_control(
>dc_link_backlight_enable_aux(link, enable);
>
>/*edp 1.2*/
>-   if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF)
>-   edp_add_delay_for_T9(link);
>+   if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) {
>+   if (!link->dc->config.edp_no_power_sequencing)
>+   /*
>+* Sometimes, DP receiver chip power-controlled externally by 
>an
>+* Embedded Controller could be treated and used as eDP,
>+* if it drives mobile display. In this case,
>+* we shouldn't be doing 

[PATCH] drm/amd/display: Enabling eDP no power sequencing with DAL feature mask

2021-06-21 Thread Liu, Zhan
[Public]

[Why]
Sometimes, DP receiver chip power-controlled externally by an
Embedded Controller could be treated and used as eDP,
if it drives mobile display. In this case,
we shouldn't be doing power-sequencing, hence we can skip
waiting for T7-ready and T9-ready."

[How]
Added a feature mask to enable eDP no power sequencing feature.

To enable this, set 0x10 flag in amdgpu.dcfeaturemask on
Linux command line.

Signed-off-by: Zhan Liu 
Change-Id: I15e8fb2979fe3ff5491ccf1ee384693d4dce787c
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c   |  1 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  3 ++
 drivers/gpu/drm/amd/display/dc/dc.h   |  1 +
 .../display/dc/dce110/dce110_hw_sequencer.c   | 31 ---
 drivers/gpu/drm/amd/include/amd_shared.h  | 10 +++---
 5 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 3de1accb060e..b588cf4398db 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -159,6 +159,7 @@ int amdgpu_smu_pptable_id = -1;
  * highest. That helps saving some idle power.
  * DISABLE_FRACTIONAL_PWM (bit 2) disabled by default
  * PSR (bit 3) disabled by default
+ * EDP NO POWER SEQUENCING (bit 4) disabled by default
  */
 uint amdgpu_dc_feature_mask = 2;
 uint amdgpu_dc_debug_mask;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index c0a3119982b0..abba26c8f20a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1174,6 +1174,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
if (amdgpu_dc_feature_mask & DC_DISABLE_FRACTIONAL_PWM_MASK)
init_data.flags.disable_fractional_pwm = true;

+   if (amdgpu_dc_feature_mask & DC_EDP_NO_POWER_SEQUENCING)
+   init_data.flags.edp_no_power_sequencing = true;
+
init_data.flags.power_down_display_on_boot = true;

INIT_LIST_HEAD(>dm.da_list);
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index a70697898025..7f1d2d6f9de8 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -297,6 +297,7 @@ struct dc_config {
bool allow_seamless_boot_optimization;
bool power_down_display_on_boot;
bool edp_not_connected;
+   bool edp_no_power_sequencing;
bool force_enum_edp;
bool forced_clocks;
bool allow_lttpr_non_transparent_mode;
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 53dd305fa6b0..013d94c9506a 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -1023,8 +1023,20 @@ void dce110_edp_backlight_control(
/* dc_service_sleep_in_milliseconds(50); */
/*edp 1.2*/
panel_instance = link->panel_cntl->inst;
-   if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON)
-   edp_receiver_ready_T7(link);
+
+   if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) {
+   if (!link->dc->config.edp_no_power_sequencing)
+   /*
+* Sometimes, DP receiver chip power-controlled externally by an
+* Embedded Controller could be treated and used as eDP,
+* if it drives mobile display. In this case,
+* we shouldn't be doing power-sequencing, hence we can skip
+* waiting for T7-ready.
+*/
+   edp_receiver_ready_T7(link);
+   else
+   DC_LOG_DC("edp_receiver_ready_T7 skipped\n");
+   }

if (ctx->dc->ctx->dmub_srv &&
ctx->dc->debug.dmub_command_table) {
@@ -1049,8 +1061,19 @@ void dce110_edp_backlight_control(
dc_link_backlight_enable_aux(link, enable);

/*edp 1.2*/
-   if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF)
-   edp_add_delay_for_T9(link);
+   if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) {
+   if (!link->dc->config.edp_no_power_sequencing)
+   /*
+* Sometimes, DP receiver chip power-controlled externally by an
+* Embedded Controller could be treated and used as eDP,
+* if it drives mobile display. In this case,
+* we shouldn't be doing power-sequencing, hence we can skip
+* waiting for T9-ready.
+*/
+   edp_add_delay_for_T9(link);
+   else
+   DC_LOG_DC("edp_receiver_ready_T9 skipped\n");
+   }

if (!enable && link->dpcd_sink_ext_caps.bits.oled)
msleep(OLED_PRE_T11_DELAY);
diff --git 

Re: [PATCH 10/10] drm/amdkfd: protect svm_bo ref in case prange has forked

2021-06-21 Thread Felix Kuehling

On 2021-06-21 12:04 p.m., Alex Sierra wrote:

Keep track of all the pages inside of pranges referenced to
the same svm_bo.


This description is a bit confusing because you're not tracking page 
references but BO references.




  This is done, by using the ref count inside this object.
This makes sure the object has freed after the last prange is not longer
at any GPU. Including references shared between a parent and child during
a fork.


References to the BO are not really shared between parent and child 
processes. They share page references. What we're doing here is, we're 
removing assumptions about the lifetime of the svm_bo by tying it to the 
lifetime of any pages referencing it.


I'd suggest this description:

drm/amdkfd: Maintain svm_bo reference in page->zone_device_data

Each zone-device page holds a reference to the SVM BO that manages its 
backing storage. This is necessary to correctly hold on to the BO in 
case zone_device pages are shared with a child-process.





Signed-off-by: Alex Sierra 
Change-Id: Ibfe5efbfed28c2d7681fe091264a5d0d5f3657b2


Please remove the Change-Id.



---
  drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 10 --
  drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 10 +-
  drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 10 +-
  3 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index acb9f64577a0..c8ca3252cbc2 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -245,7 +245,7 @@ svm_migrate_get_vram_page(struct svm_range *prange, 
unsigned long pfn)
struct page *page;
  
  	page = pfn_to_page(pfn);

-   page->zone_device_data = prange;
+   page->zone_device_data = prange->svm_bo;
get_page(page);
lock_page(page);
  }
@@ -336,6 +336,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct 
svm_range *prange,
svm_migrate_get_vram_page(prange, migrate->dst[i]);
migrate->dst[i] = migrate_pfn(migrate->dst[i]);
migrate->dst[i] |= MIGRATE_PFN_LOCKED;
+   svm_range_bo_ref(prange->svm_bo);


It would be cleaner to move this into svm_migrate_get_vram_page, where 
you assign the prange->svm_bo reference to page->zonde_device_data.


Regards,
  Felix



}
if (migrate->dst[i] & MIGRATE_PFN_VALID) {
spage = migrate_pfn_to_page(migrate->src[i]);
@@ -540,7 +541,12 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t 
best_loc,
  
  static void svm_migrate_page_free(struct page *page)

  {
-   /* Keep this function to avoid warning */
+   struct svm_range_bo *svm_bo = page->zone_device_data;
+
+   if (svm_bo) {
+   pr_debug("svm_bo ref left: %d\n", kref_read(_bo->kref));
+   svm_range_bo_unref(svm_bo);
+   }
  }
  
  static int

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index ebc1ae7e5193..4b5fc2375641 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -309,14 +309,6 @@ static bool svm_bo_ref_unless_zero(struct svm_range_bo 
*svm_bo)
return true;
  }
  
-static struct svm_range_bo *svm_range_bo_ref(struct svm_range_bo *svm_bo)

-{
-   if (svm_bo)
-   kref_get(_bo->kref);
-
-   return svm_bo;
-}
-
  static void svm_range_bo_release(struct kref *kref)
  {
struct svm_range_bo *svm_bo;
@@ -355,7 +347,7 @@ static void svm_range_bo_release(struct kref *kref)
kfree(svm_bo);
  }
  
-static void svm_range_bo_unref(struct svm_range_bo *svm_bo)

+void svm_range_bo_unref(struct svm_range_bo *svm_bo)
  {
if (!svm_bo)
return;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index 27fbe1936493..21f693767a0d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -150,6 +150,14 @@ static inline void svm_range_unlock(struct svm_range 
*prange)
mutex_unlock(>lock);
  }
  
+static inline struct svm_range_bo *svm_range_bo_ref(struct svm_range_bo *svm_bo)

+{
+   if (svm_bo)
+   kref_get(_bo->kref);
+
+   return svm_bo;
+}
+
  int svm_range_list_init(struct kfd_process *p);
  void svm_range_list_fini(struct kfd_process *p);
  int svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start,
@@ -178,7 +186,7 @@ void svm_range_dma_unmap(struct device *dev, dma_addr_t 
*dma_addr,
  void svm_range_free_dma_mappings(struct svm_range *prange);
  void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm,
void *owner);
-
+void svm_range_bo_unref(struct svm_range_bo *svm_bo);
  #else
  
  struct kfd_process;

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org

[pull] amdgpu drm-fixes-5.13

2021-06-21 Thread Alex Deucher
Hi Dave, Daniel,

Last minute fixes for 5.13.

The following changes since commit 13311e74253fe64329390df80bed3f07314ddd61:

  Linux 5.13-rc7 (2021-06-20 15:03:15 -0700)

are available in the Git repository at:

  https://gitlab.freedesktop.org/agd5f/linux.git 
tags/amd-drm-fixes-5.13-2021-06-21

for you to fetch changes up to ee5468b9f1d3bf48082eed351dace14598e8ca39:

  Revert "drm/amdgpu/gfx9: fix the doorbell missing when in CGPG issue." 
(2021-06-21 17:22:52 -0400)


amd-drm-fixes-5.13-2021-06-21:

amdgpu:
- Revert GFX9, 10 doorbell fixes, we just
  end up trading one bug for another
- Potential memory corruption fix in framebuffer handling


Michel Dänzer (1):
  drm/amdgpu: Call drm_framebuffer_init last for framebuffer init

Yifan Zhang (2):
  Revert "drm/amdgpu/gfx10: enlarge CP_MEC_DOORBELL_RANGE_UPPER to cover 
full doorbell."
  Revert "drm/amdgpu/gfx9: fix the doorbell missing when in CGPG issue."

 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 12 +++-
 drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c  |  6 +-
 drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c   |  6 +-
 3 files changed, 9 insertions(+), 15 deletions(-)
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH v3 1/2] habanalabs: define uAPI to export FD for DMA-BUF

2021-06-21 Thread Jason Gunthorpe
On Mon, Jun 21, 2021 at 10:24:16PM +0300, Oded Gabbay wrote:

> Another thing I want to emphasize is that we are doing p2p only
> through the export/import of the FD. We do *not* allow the user to
> mmap the dma-buf as we do not support direct IO. So there is no access
> to these pages through the userspace.

Arguably mmaping the memory is a better choice, and is the direction
that Logan's series goes in. Here the use of DMABUF was specifically
designed to allow hitless revokation of the memory, which this isn't
even using.

So you are taking the hit of very limited hardware support and reduced
performance just to squeeze into DMABUF..

Jason
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH] drm/amdgpu/display: fold DRM_AMD_DC_DCN3_1 into DRM_AMD_DC_DCN

2021-06-21 Thread Kazlauskas, Nicholas

On 2021-06-21 4:58 p.m., Alex Deucher wrote:

No need for a separate flag now that DCN3.1 is not in bring up.
Fold into DRM_AMD_DC_DCN like previous DCN IPs.

Signed-off-by: Alex Deucher 


Reviewed-by: Nicholas Kazlauskas 

Regards,
Nicholas Kazlauskas


---
  drivers/gpu/drm/amd/display/Kconfig   |  7 --
  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 22 +--
  .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c|  4 
  drivers/gpu/drm/amd/display/dc/Makefile   |  2 --
  .../drm/amd/display/dc/bios/bios_parser2.c|  7 +-
  .../display/dc/bios/command_table_helper2.c   |  6 +
  .../gpu/drm/amd/display/dc/clk_mgr/Makefile   |  2 --
  .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c  |  7 --
  .../display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c  |  2 --
  drivers/gpu/drm/amd/display/dc/core/dc.c  |  8 +++
  drivers/gpu/drm/amd/display/dc/core/dc_link.c |  6 ++---
  .../gpu/drm/amd/display/dc/core/dc_resource.c | 10 ++---
  .../gpu/drm/amd/display/dc/core/dc_stream.c   |  4 
  drivers/gpu/drm/amd/display/dc/dc.h   | 14 +---
  drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c  |  3 +--
  drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h  |  3 +--
  .../gpu/drm/amd/display/dc/dce/dce_hwseq.h|  6 -
  .../display/dc/dce110/dce110_hw_sequencer.c   |  4 ++--
  .../drm/amd/display/dc/dcn10/dcn10_hubbub.h   |  9 +---
  .../amd/display/dc/dcn10/dcn10_link_encoder.h |  9 +---
  .../gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h |  8 ---
  .../drm/amd/display/dc/dcn20/dcn20_hubbub.h   |  2 --
  .../gpu/drm/amd/display/dc/dcn20/dcn20_hubp.h | 10 -
  .../drm/amd/display/dc/dcn20/dcn20_hwseq.c| 19 +++-
  .../drm/amd/display/dc/dcn20/dcn20_resource.c | 16 --
  .../drm/amd/display/dc/dcn30/dcn30_hwseq.c|  2 --
  .../drm/amd/display/dc/dcn31/dcn31_hwseq.c|  2 --
  drivers/gpu/drm/amd/display/dc/dm_cp_psp.h|  2 --
  drivers/gpu/drm/amd/display/dc/dml/Makefile   |  6 -
  .../dc/dml/dcn31/display_mode_vba_31.c|  2 --
  .../dc/dml/dcn31/display_rq_dlg_calc_31.c |  3 ---
  .../drm/amd/display/dc/dml/display_mode_lib.c |  9 ++--
  .../drm/amd/display/dc/dml/display_mode_lib.h |  2 --
  .../amd/display/dc/dml/display_mode_structs.h |  4 
  .../drm/amd/display/dc/dml/display_mode_vba.c | 12 --
  .../drm/amd/display/dc/dml/display_mode_vba.h |  6 -
  .../gpu/drm/amd/display/dc/gpio/hw_factory.c  |  2 --
  .../drm/amd/display/dc/gpio/hw_translate.c|  2 --
  .../gpu/drm/amd/display/dc/inc/core_types.h   |  6 -
  .../gpu/drm/amd/display/dc/inc/hw/clk_mgr.h   |  2 --
  drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h  |  6 -
  .../gpu/drm/amd/display/dc/inc/hw/dchubbub.h  |  2 --
  .../drm/amd/display/dc/inc/hw/link_encoder.h  | 14 +---
  .../gpu/drm/amd/display/dc/inc/hw/mem_input.h |  2 --
  .../amd/display/dc/inc/hw/timing_generator.h  |  2 --
  .../gpu/drm/amd/display/dc/inc/hw_sequencer.h |  2 --
  drivers/gpu/drm/amd/display/dc/irq/Makefile   |  2 --
  .../display/dc/irq/dcn31/irq_service_dcn31.h  |  3 ---
  drivers/gpu/drm/amd/display/dmub/dmub_srv.h   |  8 ---
  .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   | 14 +---
  drivers/gpu/drm/amd/display/dmub/src/Makefile |  6 +
  .../gpu/drm/amd/display/dmub/src/dmub_srv.c   |  4 
  .../gpu/drm/amd/display/include/dal_asic_id.h |  2 --
  .../gpu/drm/amd/display/include/dal_types.h   |  2 --
  .../drm/amd/display/modules/hdcp/hdcp_log.c   |  2 --
  .../drm/amd/display/modules/hdcp/hdcp_psp.c   | 18 ---
  .../drm/amd/display/modules/hdcp/hdcp_psp.h   | 13 ++-
  .../drm/amd/display/modules/inc/mod_hdcp.h| 10 -
  58 files changed, 45 insertions(+), 319 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/Kconfig 
b/drivers/gpu/drm/amd/display/Kconfig
index 5b5f36c80efb..7dffc04a557e 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -31,13 +31,6 @@ config DRM_AMD_DC_SI
  by default. This includes Tahiti, Pitcairn, Cape Verde, Oland.
  Hainan is not supported by AMD DC and it has no physical DCE6.
  
-config DRM_AMD_DC_DCN3_1

-bool "DCN 3.1 family"
-depends on DRM_AMD_DC_DCN
-help
-Choose this option if you want to have
-DCN3.1 family support for display engine
-
  config DEBUG_KERNEL_DC
bool "Enable kgdb break in DC"
depends on DRM_AMD_DC
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index d069661abe45..b5b5ccf0ed71 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -110,10 +110,8 @@ MODULE_FIRMWARE(FIRMWARE_VANGOGH_DMUB);
  MODULE_FIRMWARE(FIRMWARE_DIMGREY_CAVEFISH_DMUB);
  #define FIRMWARE_BEIGE_GOBY_DMUB "amdgpu/beige_goby_dmcub.bin"
  MODULE_FIRMWARE(FIRMWARE_BEIGE_GOBY_DMUB);
-#if 

Re: [PATCH 08/10] drm/amdkfd: add invalid pages debug at vram migration

2021-06-21 Thread Felix Kuehling

On 2021-06-21 12:04 p.m., Alex Sierra wrote:

This is for debug purposes only.
It conditionally generates partial migrations to test mixed
CPU/GPU memory domain pages in a prange easily.

Signed-off-by: Alex Sierra 


Reviewed-by: Felix Kuehling 



---
  drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 14 ++
  1 file changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 8a3f21d76915..f71f8d7e2b72 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -404,6 +404,20 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, 
struct svm_range *prange,
}
}
  
+#ifdef DEBUG_FORCE_MIXED_DOMAINS

+   for (i = 0, j = 0; i < npages; i += 4, j++) {
+   if (j & 1)
+   continue;
+   svm_migrate_put_vram_page(adev, dst[i]);
+   migrate->dst[i] = 0;
+   svm_migrate_put_vram_page(adev, dst[i + 1]);
+   migrate->dst[i + 1] = 0;
+   svm_migrate_put_vram_page(adev, dst[i + 2]);
+   migrate->dst[i + 2] = 0;
+   svm_migrate_put_vram_page(adev, dst[i + 3]);
+   migrate->dst[i + 3] = 0;
+   }
+#endif
  out:
return r;
  }

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH 07/10] drm/amdkfd: skip migration for pages already in VRAM

2021-06-21 Thread Felix Kuehling

On 2021-06-21 12:04 p.m., Alex Sierra wrote:

Migration skipped for pages that are already in VRAM
domain. These could be the result of previous partial
migrations to SYS RAM, and prefetch back to VRAM.
Ex. Coherent pages in VRAM that were not written/invalidated after
a copy-on-write.

Signed-off-by: Alex Sierra 
---
  drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 17 +
  1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 6fd68528c425..8a3f21d76915 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -329,14 +329,15 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, 
struct svm_range *prange,
for (i = j = 0; i < npages; i++) {
struct page *spage;
  
-		dst[i] = vram_addr + (j << PAGE_SHIFT);

-   migrate->dst[i] = svm_migrate_addr_to_pfn(adev, dst[i]);
-   svm_migrate_get_vram_page(prange, migrate->dst[i]);
-
-   migrate->dst[i] = migrate_pfn(migrate->dst[i]);
-   migrate->dst[i] |= MIGRATE_PFN_LOCKED;
-
-   if (migrate->src[i] & MIGRATE_PFN_VALID) {
+   spage = migrate_pfn_to_page(migrate->src[i]);
+   if (spage && !is_zone_device_page(spage)) {
+   dst[i] = vram_addr + (j << PAGE_SHIFT);
+   migrate->dst[i] = svm_migrate_addr_to_pfn(adev, dst[i]);
+   svm_migrate_get_vram_page(prange, migrate->dst[i]);
+   migrate->dst[i] = migrate_pfn(migrate->dst[i]);
+   migrate->dst[i] |= MIGRATE_PFN_LOCKED;
+   }
+   if (migrate->dst[i] & MIGRATE_PFN_VALID) {
spage = migrate_pfn_to_page(migrate->src[i]);


I think spage is already set correctly here. You shouldn't need to 
assign it again.


Also, is this condition (migrate->dst[i] & MIGRATE_PFN_VALID) really 
needed? It seems to me, migrate_pfn sets that flag unconditionally. So 
you can just continue the previous if-block.


Regards,
  Felix



src[i] = dma_map_page(dev, spage, 0, PAGE_SIZE,
  DMA_TO_DEVICE);

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH] drm/amdgpu/display: fold DRM_AMD_DC_DCN3_1 into DRM_AMD_DC_DCN

2021-06-21 Thread Alex Deucher
No need for a separate flag now that DCN3.1 is not in bring up.
Fold into DRM_AMD_DC_DCN like previous DCN IPs.

Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/display/Kconfig   |  7 --
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 22 +--
 .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c|  4 
 drivers/gpu/drm/amd/display/dc/Makefile   |  2 --
 .../drm/amd/display/dc/bios/bios_parser2.c|  7 +-
 .../display/dc/bios/command_table_helper2.c   |  6 +
 .../gpu/drm/amd/display/dc/clk_mgr/Makefile   |  2 --
 .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c  |  7 --
 .../display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c  |  2 --
 drivers/gpu/drm/amd/display/dc/core/dc.c  |  8 +++
 drivers/gpu/drm/amd/display/dc/core/dc_link.c |  6 ++---
 .../gpu/drm/amd/display/dc/core/dc_resource.c | 10 ++---
 .../gpu/drm/amd/display/dc/core/dc_stream.c   |  4 
 drivers/gpu/drm/amd/display/dc/dc.h   | 14 +---
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c  |  3 +--
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h  |  3 +--
 .../gpu/drm/amd/display/dc/dce/dce_hwseq.h|  6 -
 .../display/dc/dce110/dce110_hw_sequencer.c   |  4 ++--
 .../drm/amd/display/dc/dcn10/dcn10_hubbub.h   |  9 +---
 .../amd/display/dc/dcn10/dcn10_link_encoder.h |  9 +---
 .../gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h |  8 ---
 .../drm/amd/display/dc/dcn20/dcn20_hubbub.h   |  2 --
 .../gpu/drm/amd/display/dc/dcn20/dcn20_hubp.h | 10 -
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c| 19 +++-
 .../drm/amd/display/dc/dcn20/dcn20_resource.c | 16 --
 .../drm/amd/display/dc/dcn30/dcn30_hwseq.c|  2 --
 .../drm/amd/display/dc/dcn31/dcn31_hwseq.c|  2 --
 drivers/gpu/drm/amd/display/dc/dm_cp_psp.h|  2 --
 drivers/gpu/drm/amd/display/dc/dml/Makefile   |  6 -
 .../dc/dml/dcn31/display_mode_vba_31.c|  2 --
 .../dc/dml/dcn31/display_rq_dlg_calc_31.c |  3 ---
 .../drm/amd/display/dc/dml/display_mode_lib.c |  9 ++--
 .../drm/amd/display/dc/dml/display_mode_lib.h |  2 --
 .../amd/display/dc/dml/display_mode_structs.h |  4 
 .../drm/amd/display/dc/dml/display_mode_vba.c | 12 --
 .../drm/amd/display/dc/dml/display_mode_vba.h |  6 -
 .../gpu/drm/amd/display/dc/gpio/hw_factory.c  |  2 --
 .../drm/amd/display/dc/gpio/hw_translate.c|  2 --
 .../gpu/drm/amd/display/dc/inc/core_types.h   |  6 -
 .../gpu/drm/amd/display/dc/inc/hw/clk_mgr.h   |  2 --
 drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h  |  6 -
 .../gpu/drm/amd/display/dc/inc/hw/dchubbub.h  |  2 --
 .../drm/amd/display/dc/inc/hw/link_encoder.h  | 14 +---
 .../gpu/drm/amd/display/dc/inc/hw/mem_input.h |  2 --
 .../amd/display/dc/inc/hw/timing_generator.h  |  2 --
 .../gpu/drm/amd/display/dc/inc/hw_sequencer.h |  2 --
 drivers/gpu/drm/amd/display/dc/irq/Makefile   |  2 --
 .../display/dc/irq/dcn31/irq_service_dcn31.h  |  3 ---
 drivers/gpu/drm/amd/display/dmub/dmub_srv.h   |  8 ---
 .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   | 14 +---
 drivers/gpu/drm/amd/display/dmub/src/Makefile |  6 +
 .../gpu/drm/amd/display/dmub/src/dmub_srv.c   |  4 
 .../gpu/drm/amd/display/include/dal_asic_id.h |  2 --
 .../gpu/drm/amd/display/include/dal_types.h   |  2 --
 .../drm/amd/display/modules/hdcp/hdcp_log.c   |  2 --
 .../drm/amd/display/modules/hdcp/hdcp_psp.c   | 18 ---
 .../drm/amd/display/modules/hdcp/hdcp_psp.h   | 13 ++-
 .../drm/amd/display/modules/inc/mod_hdcp.h| 10 -
 58 files changed, 45 insertions(+), 319 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/Kconfig 
b/drivers/gpu/drm/amd/display/Kconfig
index 5b5f36c80efb..7dffc04a557e 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -31,13 +31,6 @@ config DRM_AMD_DC_SI
  by default. This includes Tahiti, Pitcairn, Cape Verde, Oland.
  Hainan is not supported by AMD DC and it has no physical DCE6.
 
-config DRM_AMD_DC_DCN3_1
-bool "DCN 3.1 family"
-depends on DRM_AMD_DC_DCN
-help
-Choose this option if you want to have
-DCN3.1 family support for display engine
-
 config DEBUG_KERNEL_DC
bool "Enable kgdb break in DC"
depends on DRM_AMD_DC
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index d069661abe45..b5b5ccf0ed71 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -110,10 +110,8 @@ MODULE_FIRMWARE(FIRMWARE_VANGOGH_DMUB);
 MODULE_FIRMWARE(FIRMWARE_DIMGREY_CAVEFISH_DMUB);
 #define FIRMWARE_BEIGE_GOBY_DMUB "amdgpu/beige_goby_dmcub.bin"
 MODULE_FIRMWARE(FIRMWARE_BEIGE_GOBY_DMUB);
-#if defined(CONFIG_DRM_AMD_DC_DCN3_1)
 #define FIRMWARE_YELLOW_CARP_DMUB "amdgpu/yellow_carp_dmcub.bin"
 MODULE_FIRMWARE(FIRMWARE_YELLOW_CARP_DMUB);
-#endif
 
 #define FIRMWARE_RAVEN_DMCU

Re: [PATCH 05/10] drm/amdkfd: classify and map mixed svm range pages in GPU

2021-06-21 Thread Felix Kuehling

On 2021-06-21 12:04 p.m., Alex Sierra wrote:

[Why]
svm ranges can have mixed pages from device or system memory.
A good example is, after a prange has been allocated in VRAM and a
copy-on-write is triggered by a fork. This invalidates some pages
inside the prange. Endding up in mixed pages.

[How]
By classifying each page inside a prange, based on its type. Device or
system memory, during dma mapping call. If page corresponds
to VRAM domain, a flag is set to its dma_addr entry for each GPU.
Then, at the GPU page table mapping. All group of contiguous pages within
the same type are mapped with their proper pte flags.

v2:
Instead of using ttm_res to calculate vram pfns in the svm_range. It is now
done by setting the vram real physical address into drm_addr array.
This makes more flexible VRAM management, plus removes the need to have
a BO reference in the svm_range.

v3:
Remove mapping member from svm_range

Signed-off-by: Alex Sierra 


Reviewed-by: Felix Kuehling 



---
  drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 73 ++--
  drivers/gpu/drm/amd/amdkfd/kfd_svm.h |  2 +-
  2 files changed, 47 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 2b4318646a75..3b05bc270732 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -119,11 +119,12 @@ static void svm_range_remove_notifier(struct svm_range 
*prange)
  }
  
  static int

-svm_range_dma_map_dev(struct device *dev, dma_addr_t **dma_addr,
+svm_range_dma_map_dev(struct amdgpu_device *adev, dma_addr_t **dma_addr,
  unsigned long *hmm_pfns, uint64_t npages)
  {
enum dma_data_direction dir = DMA_BIDIRECTIONAL;
dma_addr_t *addr = *dma_addr;
+   struct device *dev = adev->dev;
struct page *page;
int i, r;
  
@@ -141,6 +142,14 @@ svm_range_dma_map_dev(struct device *dev, dma_addr_t **dma_addr,

dma_unmap_page(dev, addr[i], PAGE_SIZE, dir);
  
  		page = hmm_pfn_to_page(hmm_pfns[i]);

+   if (is_zone_device_page(page)) {
+   addr[i] = (hmm_pfns[i] << PAGE_SHIFT) +
+  adev->vm_manager.vram_base_offset -
+  adev->kfd.dev->pgmap.range.start;
+   addr[i] |= SVM_RANGE_VRAM_DOMAIN;
+   pr_debug("vram address detected: 0x%llx\n", addr[i]);
+   continue;
+   }
addr[i] = dma_map_page(dev, page, 0, PAGE_SIZE, dir);
r = dma_mapping_error(dev, addr[i]);
if (r) {
@@ -175,7 +184,7 @@ svm_range_dma_map(struct svm_range *prange, unsigned long 
*bitmap,
}
adev = (struct amdgpu_device *)pdd->dev->kgd;
  
-		r = svm_range_dma_map_dev(adev->dev, >dma_addr[gpuidx],

+   r = svm_range_dma_map_dev(adev, >dma_addr[gpuidx],
  hmm_pfns, prange->npages);
if (r)
break;
@@ -1003,21 +1012,22 @@ svm_range_split_by_granularity(struct kfd_process *p, 
struct mm_struct *mm,
  }
  
  static uint64_t

-svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange)
+svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange,
+   int domain)
  {
struct amdgpu_device *bo_adev;
uint32_t flags = prange->flags;
uint32_t mapping_flags = 0;
uint64_t pte_flags;
-   bool snoop = !prange->ttm_res;
+   bool snoop = (domain != SVM_RANGE_VRAM_DOMAIN);
bool coherent = flags & KFD_IOCTL_SVM_FLAG_COHERENT;
  
-	if (prange->svm_bo && prange->ttm_res)

+   if (domain == SVM_RANGE_VRAM_DOMAIN)
bo_adev = amdgpu_ttm_adev(prange->svm_bo->bo->tbo.bdev);
  
  	switch (adev->asic_type) {

case CHIP_ARCTURUS:
-   if (prange->svm_bo && prange->ttm_res) {
+   if (domain == SVM_RANGE_VRAM_DOMAIN) {
if (bo_adev == adev) {
mapping_flags |= coherent ?
AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW;
@@ -1032,7 +1042,7 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, 
struct svm_range *prange)
}
break;
case CHIP_ALDEBARAN:
-   if (prange->svm_bo && prange->ttm_res) {
+   if (domain == SVM_RANGE_VRAM_DOMAIN) {
if (bo_adev == adev) {
mapping_flags |= coherent ?
AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW;
@@ -1061,14 +1071,14 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, 
struct svm_range *prange)
mapping_flags |= AMDGPU_VM_PAGE_EXECUTABLE;
  
  	pte_flags = AMDGPU_PTE_VALID;

-   pte_flags |= prange->ttm_res ? 0 : AMDGPU_PTE_SYSTEM;
+   pte_flags |= 

Re: [PATCH 04/10] drm/amdgpu: get owner ref in validate and map

2021-06-21 Thread Felix Kuehling

On 2021-06-21 12:04 p.m., Alex Sierra wrote:

Get the proper owner reference for amdgpu_hmm_range_get_pages function.
This is useful for partial migrations. To avoid migrating back to
system memory, VRAM pages, that are accessible by all devices in the
same memory domain.
Ex. multiple devices in the same hive.

Signed-off-by: Alex Sierra 


Reviewed-by: Felix Kuehling 



---
  drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 25 -
  1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 54f47b09b14a..2b4318646a75 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1313,6 +1313,17 @@ static void svm_range_unreserve_bos(struct 
svm_validate_context *ctx)
ttm_eu_backoff_reservation(>ticket, >validate_list);
  }
  
+static void *kfd_svm_page_owner(struct kfd_process *p, int32_t gpuidx)

+{
+   struct kfd_process_device *pdd;
+   struct amdgpu_device *adev;
+
+   pdd = kfd_process_device_from_gpuidx(p, gpuidx);
+   adev = (struct amdgpu_device *)pdd->dev->kgd;
+
+   return SVM_ADEV_PGMAP_OWNER(adev);
+}
+
  /*
   * Validation+GPU mapping with concurrent invalidation (MMU notifiers)
   *
@@ -1343,6 +1354,9 @@ static int svm_range_validate_and_map(struct mm_struct 
*mm,
  {
struct svm_validate_context ctx;
struct hmm_range *hmm_range;
+   struct kfd_process *p;
+   void *owner;
+   int32_t idx;
int r = 0;
  
  	ctx.process = container_of(prange->svms, struct kfd_process, svms);

@@ -1389,10 +1403,19 @@ static int svm_range_validate_and_map(struct mm_struct 
*mm,
svm_range_reserve_bos();
  
  	if (!prange->actual_loc) {

+   p = container_of(prange->svms, struct kfd_process, svms);
+   owner = kfd_svm_page_owner(p, find_first_bit(ctx.bitmap,
+   MAX_GPU_INSTANCE));
+   for_each_set_bit(idx, ctx.bitmap, MAX_GPU_INSTANCE) {
+   if (kfd_svm_page_owner(p, idx) != owner) {
+   owner = NULL;
+   break;
+   }
+   }
r = amdgpu_hmm_range_get_pages(>notifier, mm, NULL,
   prange->start << PAGE_SHIFT,
   prange->npages, _range,
-  false, true, NULL);
+  false, true, owner);
if (r) {
pr_debug("failed %d to get svm range pages\n", r);
goto unreserve_out;

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH 02/10] drm/amdkfd: add owner ref param to get hmm pages

2021-06-21 Thread Felix Kuehling

On 2021-06-21 12:04 p.m., Alex Sierra wrote:

The parameter is used in the dev_private_owner to decide if device
pages in the range require to be migrated back to system memory, based
if they are or not in the same memory domain.
In this case, this reference could come from the same memory domain
with devices connected to the same hive.

Signed-off-by: Alex Sierra 


Reviewed-by: Felix Kuehling 



---
  drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c  | 3 ++-
  drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h  | 2 +-
  drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +-
  drivers/gpu/drm/amd/amdkfd/kfd_svm.c| 4 ++--
  4 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
index 2741c28ff1b5..378c238c2099 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
@@ -160,7 +160,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier 
*notifier,
   struct mm_struct *mm, struct page **pages,
   uint64_t start, uint64_t npages,
   struct hmm_range **phmm_range, bool readonly,
-  bool mmap_locked)
+  bool mmap_locked, void *owner)
  {
struct hmm_range *hmm_range;
unsigned long timeout;
@@ -185,6 +185,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier 
*notifier,
hmm_range->hmm_pfns = pfns;
hmm_range->start = start;
hmm_range->end = start + npages * PAGE_SIZE;
+   hmm_range->dev_private_owner = owner;
  
  	/* Assuming 512MB takes maxmium 1 second to fault page address */

timeout = max(npages >> 17, 1ULL) * HMM_RANGE_DEFAULT_TIMEOUT;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
index 7f7d37a457c3..14a3c1864085 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
@@ -34,7 +34,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier 
*notifier,
   struct mm_struct *mm, struct page **pages,
   uint64_t start, uint64_t npages,
   struct hmm_range **phmm_range, bool readonly,
-  bool mmap_locked);
+  bool mmap_locked, void *owner);
  int amdgpu_hmm_range_get_pages_done(struct hmm_range *hmm_range);
  
  #if defined(CONFIG_HMM_MIRROR)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 7e7d8330d64b..c13f7fbfc070 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -709,7 +709,7 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, 
struct page **pages)
readonly = amdgpu_ttm_tt_is_readonly(ttm);
r = amdgpu_hmm_range_get_pages(>notifier, mm, pages, start,
   ttm->num_pages, >range, readonly,
-  false);
+  false, NULL);
  out_putmm:
mmput(mm);
  
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c

index b665e9ff77e3..b939f353ac8c 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1392,7 +1392,7 @@ static int svm_range_validate_and_map(struct mm_struct 
*mm,
r = amdgpu_hmm_range_get_pages(>notifier, mm, NULL,
   prange->start << PAGE_SHIFT,
   prange->npages, _range,
-  false, true);
+  false, true, NULL);
if (r) {
pr_debug("failed %d to get svm range pages\n", r);
goto unreserve_out;
@@ -2657,7 +2657,7 @@ void svm_range_prefault(struct svm_range *prange, struct 
mm_struct *mm)
r = amdgpu_hmm_range_get_pages(>notifier, mm, NULL,
   prange->start << PAGE_SHIFT,
   prange->npages, _range,
-  false, true);
+  false, true, NULL);
if (!r) {
amdgpu_hmm_range_get_pages_done(hmm_range);
prange->validated_once = true;

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH 01/10] drm/amdkfd: device pgmap owner at the svm migrate init

2021-06-21 Thread Felix Kuehling

On 2021-06-21 12:04 p.m., Alex Sierra wrote:

pgmap owner member at the svm migrate init could be referenced
to either adev or hive, depending on device topology.


The reasoning for this change is, that GPUs in the same XGMI hive have 
direct access to all members' VRAM. When mapping memory to a GPU, we 
don't need hmm_range_fault to fault device-private pages in the same 
hive back to the host. Identifying the page owner as the hive, rather 
than the individual GPU, accomplishes this.


With this explanation in the commit description, the patch is

Reviewed-by: Felix Kuehling 



Signed-off-by: Alex Sierra 
---
  drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 6 +++---
  drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 3 +++
  2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index fd8f544f0de2..11f7f590c6ec 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -426,7 +426,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct 
svm_range *prange,
migrate.start = start;
migrate.end = end;
migrate.flags = MIGRATE_VMA_SELECT_SYSTEM;
-   migrate.pgmap_owner = adev;
+   migrate.pgmap_owner = SVM_ADEV_PGMAP_OWNER(adev);
  
  	size = 2 * sizeof(*migrate.src) + sizeof(uint64_t) + sizeof(dma_addr_t);

size *= npages;
@@ -641,7 +641,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct 
svm_range *prange,
migrate.start = start;
migrate.end = end;
migrate.flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
-   migrate.pgmap_owner = adev;
+   migrate.pgmap_owner = SVM_ADEV_PGMAP_OWNER(adev);
  
  	size = 2 * sizeof(*migrate.src) + sizeof(uint64_t) + sizeof(dma_addr_t);

size *= npages;
@@ -907,7 +907,7 @@ int svm_migrate_init(struct amdgpu_device *adev)
pgmap->range.start = res->start;
pgmap->range.end = res->end;
pgmap->ops = _migrate_pgmap_ops;
-   pgmap->owner = adev;
+   pgmap->owner = SVM_ADEV_PGMAP_OWNER(adev);
pgmap->flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
r = devm_memremap_pages(adev->dev, pgmap);
if (IS_ERR(r)) {
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index 573f984b81fe..4297250f259d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -35,6 +35,9 @@
  #include "amdgpu.h"
  #include "kfd_priv.h"
  
+#define SVM_ADEV_PGMAP_OWNER(adev)\

+   ((adev)->hive ? (void *)(adev)->hive : (void *)(adev))
+
  struct svm_range_bo {
struct amdgpu_bo*bo;
struct kref kref;

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 4/4] drm/amdkfd: add direct link flag to link properties

2021-06-21 Thread Jonathan Kim
Flag peers as a direct link if over PCIe or over xGMI if they are adjacent
in the hive.

Signed-off-by: Jonathan Kim 
---
 drivers/gpu/drm/amd/amdkfd/kfd_crat.h |  3 ++-
 drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 11 +++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h 
b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
index d1f6de5edfb9..0d661d60ece6 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
@@ -232,8 +232,9 @@ struct crat_subtype_ccompute {
 #define CRAT_IOLINK_FLAGS_NO_ATOMICS_32_BIT(1 << 2)
 #define CRAT_IOLINK_FLAGS_NO_ATOMICS_64_BIT(1 << 3)
 #define CRAT_IOLINK_FLAGS_NO_PEER_TO_PEER_DMA  (1 << 4)
+#define CRAT_IOLINK_FLAGS_DIRECT_LINK  (1 << 5)
 #define CRAT_IOLINK_FLAGS_BI_DIRECTIONAL   (1 << 31)
-#define CRAT_IOLINK_FLAGS_RESERVED_MASK0x7fe0
+#define CRAT_IOLINK_FLAGS_RESERVED_MASK0x7fc0
 
 /*
  * IO interface types
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index b1ce072aa20b..037fa12ac1bc 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -1244,6 +1244,15 @@ static void kfd_set_iolink_non_coherent(struct 
kfd_topology_device *to_dev,
}
 }
 
+static void kfd_set_iolink_direct_link(struct kfd_topology_device *dev,
+   struct kfd_iolink_properties *link)
+{
+   if (link->iolink_type == CRAT_IOLINK_TYPE_PCIEXPRESS ||
+   (link->iolink_type == CRAT_IOLINK_TYPE_XGMI &&
+   link->max_bandwidth))
+   link->flags |= CRAT_IOLINK_FLAGS_DIRECT_LINK;
+}
+
 static void kfd_fill_iolink_non_crat_info(struct kfd_topology_device *dev)
 {
struct kfd_iolink_properties *link, *inbound_link;
@@ -1256,6 +1265,7 @@ static void kfd_fill_iolink_non_crat_info(struct 
kfd_topology_device *dev)
list_for_each_entry(link, >io_link_props, list) {
link->flags = CRAT_IOLINK_FLAGS_ENABLED;
kfd_set_iolink_no_atomics(dev, NULL, link);
+   kfd_set_iolink_direct_link(dev, link);
peer_dev = kfd_topology_device_by_proximity_domain(
link->node_to);
 
@@ -1270,6 +1280,7 @@ static void kfd_fill_iolink_non_crat_info(struct 
kfd_topology_device *dev)
inbound_link->flags = CRAT_IOLINK_FLAGS_ENABLED;
kfd_set_iolink_no_atomics(peer_dev, dev, inbound_link);
kfd_set_iolink_non_coherent(peer_dev, link, 
inbound_link);
+   kfd_set_iolink_direct_link(peer_dev, inbound_link);
}
}
 }
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 3/4] drm/amdkfd: report pcie bandwidth as number of lanes

2021-06-21 Thread Jonathan Kim
Similar to xGMI reporting the min/max bandwidth as the number of links
between peers, PCIe will report the min/max bandwidth as the number of
supported lanes.

Signed-off-by: Jonathan Kim 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 24 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h |  3 +++
 drivers/gpu/drm/amd/amdkfd/kfd_crat.c  |  3 +++
 3 files changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index c84989eda8eb..99c662b70519 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -568,6 +568,30 @@ uint8_t amdgpu_amdkfd_get_xgmi_num_links(struct kgd_dev 
*dst, struct kgd_dev *sr
return  (uint8_t)ret;
 }
 
+uint32_t amdgpu_amdkfd_get_pcie_min_lanes(struct kgd_dev *dev)
+{
+   struct amdgpu_device *adev = (struct amdgpu_device *)dev;
+   int min_lane_shift = ffs(adev->pm.pcie_mlw_mask >>
+   CAIL_PCIE_LINK_WIDTH_SUPPORT_SHIFT) - 1;
+
+   if (min_lane_shift < 0)
+   return 0;
+
+   return 1UL << min_lane_shift;
+}
+
+uint32_t amdgpu_amdkfd_get_pcie_max_lanes(struct kgd_dev *dev)
+{
+   struct amdgpu_device *adev = (struct amdgpu_device *)dev;
+   int max_lane_shift = fls(adev->pm.pcie_mlw_mask >>
+   CAIL_PCIE_LINK_WIDTH_SUPPORT_SHIFT) - 1;
+
+   if (max_lane_shift < 0)
+   return 0;
+
+   return 1UL << max_lane_shift;
+}
+
 uint64_t amdgpu_amdkfd_get_mmio_remap_phys_addr(struct kgd_dev *kgd)
 {
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index 20e4bfce62be..88322c72a43d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include "amd_pcie.h"
 #include "amdgpu_sync.h"
 #include "amdgpu_vm.h"
 
@@ -227,6 +228,8 @@ uint32_t amdgpu_amdkfd_get_asic_rev_id(struct kgd_dev *kgd);
 int amdgpu_amdkfd_get_noretry(struct kgd_dev *kgd);
 uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev 
*src);
 uint8_t amdgpu_amdkfd_get_xgmi_num_links(struct kgd_dev *dst, struct kgd_dev 
*src);
+uint32_t amdgpu_amdkfd_get_pcie_min_lanes(struct kgd_dev *dev);
+uint32_t amdgpu_amdkfd_get_pcie_max_lanes(struct kgd_dev *dev);
 
 /* Read user wptr from a specified user address space with page fault
  * disabled. The memory must be pinned and mapped to the hardware when
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index 75047b77649b..f70d69035fe7 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -1036,6 +1036,7 @@ static int kfd_parse_subtype_iolink(struct 
crat_subtype_iolink *iolink,
props->max_latency = iolink->maximum_latency;
props->min_bandwidth = iolink->minimum_bandwidth;
props->max_bandwidth = iolink->maximum_bandwidth;
+
props->rec_transfer_size =
iolink->recommended_transfer_size;
 
@@ -1993,6 +1994,8 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int 
*avail_size,
sub_type_hdr->maximum_bandwidth = 1;
} else {
sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_PCIEXPRESS;
+   sub_type_hdr->minimum_bandwidth = 
amdgpu_amdkfd_get_pcie_min_lanes(kdev->kgd);
+   sub_type_hdr->maximum_bandwidth = 
amdgpu_amdkfd_get_pcie_max_lanes(kdev->kgd);
}
 
sub_type_hdr->proximity_domain_from = proximity_domain;
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 1/4] drm/amdgpu: add psp command to get num xgmi links between direct peers

2021-06-21 Thread Jonathan Kim
The TA can now be invoked to provide the number of xgmi links connecting
a direct source and destination peer.
Non-direct peers will report zero links.

Signed-off-by: Jonathan Kim 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 23 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h |  1 +
 drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h | 14 +-
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 40da29d8ec1e..2af9a7a9b7de 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -1037,6 +1037,12 @@ int psp_xgmi_get_node_id(struct psp_context *psp, 
uint64_t *node_id)
return 0;
 }
 
+static bool psp_xgmi_peer_link_info_supported(struct psp_context *psp)
+{
+   return psp->adev->asic_type == CHIP_ALDEBARAN &&
+   psp->ta_xgmi_ucode_version >= 0x200b;
+}
+
 int psp_xgmi_get_topology_info(struct psp_context *psp,
   int number_devices,
   struct psp_xgmi_topology_info *topology)
@@ -1080,6 +1086,23 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
topology->nodes[i].sdma_engine = 
topology_info_output->nodes[i].sdma_engine;
}
 
+   /* Invoke xgmi ta again to get the link information */
+   if (psp_xgmi_peer_link_info_supported(psp)) {
+   struct ta_xgmi_cmd_get_peer_link_info_output *link_info_output;
+
+   xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_PEER_LINKS;
+
+   ret = psp_xgmi_invoke(psp, TA_COMMAND_XGMI__GET_PEER_LINKS);
+
+   if (ret)
+   return ret;
+
+   link_info_output = _cmd->xgmi_out_message.get_link_info;
+   for (i = 0; i < topology->num_nodes; i++)
+   topology->nodes[i].num_links =
+   link_info_output->nodes[i].num_links;
+   }
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index e5dcc6713861..13f1b869f67e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -116,6 +116,7 @@ struct psp_xgmi_node_info {
uint8_t num_hops;
uint8_t is_sharing_enabled;
enum ta_xgmi_assigned_sdma_engine   sdma_engine;
+   uint8_t num_links;
 };
 
 struct psp_xgmi_topology_info {
diff --git a/drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h 
b/drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h
index ac2c27b7630c..cce7127afeaa 100644
--- a/drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h
+++ b/drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h
@@ -33,7 +33,8 @@ enum ta_command_xgmi {
TA_COMMAND_XGMI__GET_NODE_ID= 0x01,
TA_COMMAND_XGMI__GET_HIVE_ID= 0x02,
TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO  = 0x03,
-   TA_COMMAND_XGMI__SET_TOPOLOGY_INFO  = 0x04
+   TA_COMMAND_XGMI__SET_TOPOLOGY_INFO  = 0x04,
+   TA_COMMAND_XGMI__GET_PEER_LINKS = 0x0B
 };
 
 /* XGMI related enumerations */
@@ -75,6 +76,11 @@ struct ta_xgmi_node_info {
enum ta_xgmi_assigned_sdma_engine   sdma_engine;
 };
 
+struct ta_xgmi_peer_link_info {
+   uint64_tnode_id;
+   uint8_t num_links;
+};
+
 struct ta_xgmi_cmd_initialize_output {
uint32_tstatus;
 };
@@ -97,6 +103,11 @@ struct ta_xgmi_cmd_get_topology_info_output {
struct ta_xgmi_node_infonodes[TA_XGMI__MAX_CONNECTED_NODES];
 };
 
+struct ta_xgmi_cmd_get_peer_link_info_output {
+   uint32_tnum_nodes;
+   struct ta_xgmi_peer_link_info   nodes[TA_XGMI__MAX_CONNECTED_NODES];
+};
+
 struct ta_xgmi_cmd_set_topology_info_input {
uint32_tnum_nodes;
struct ta_xgmi_node_infonodes[TA_XGMI__MAX_CONNECTED_NODES];
@@ -115,6 +126,7 @@ union ta_xgmi_cmd_output {
struct ta_xgmi_cmd_get_node_id_output   get_node_id;
struct ta_xgmi_cmd_get_hive_id_output   get_hive_id;
struct ta_xgmi_cmd_get_topology_info_output get_topology_info;
+   struct ta_xgmi_cmd_get_peer_link_info_outputget_link_info;
 };
 /**/
 
-- 
2.25.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 2/4] drm/amdkfd: report num xgmi links between direct peers to the kfd

2021-06-21 Thread Jonathan Kim
Since Min/Max bandwidth was never used, it will repurposed to report the
number of xgmi links between direct peers to the KFD topology.

Signed-off-by: Jonathan Kim 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 15 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c   | 12 
 drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h   |  2 ++
 drivers/gpu/drm/amd/amdkfd/kfd_crat.c  | 11 +--
 drivers/gpu/drm/amd/amdkfd/kfd_crat.h  |  4 ++--
 6 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index bfab2f9fdd17..c84989eda8eb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -553,6 +553,21 @@ uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev 
*dst, struct kgd_dev *s
return  (uint8_t)ret;
 }
 
+uint8_t amdgpu_amdkfd_get_xgmi_num_links(struct kgd_dev *dst, struct kgd_dev 
*src)
+{
+   struct amdgpu_device *peer_adev = (struct amdgpu_device *)src;
+   struct amdgpu_device *adev = (struct amdgpu_device *)dst;
+   int ret = amdgpu_xgmi_get_num_links(adev, peer_adev);
+
+   if (ret < 0) {
+   DRM_ERROR("amdgpu: failed to get xgmi num links between node %d 
and %d. ret = %d\n",
+   adev->gmc.xgmi.physical_node_id,
+   peer_adev->gmc.xgmi.physical_node_id, ret);
+   ret = 0;
+   }
+   return  (uint8_t)ret;
+}
+
 uint64_t amdgpu_amdkfd_get_mmio_remap_phys_addr(struct kgd_dev *kgd)
 {
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index fabc68eec36a..20e4bfce62be 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -226,6 +226,7 @@ uint32_t amdgpu_amdkfd_get_num_gws(struct kgd_dev *kgd);
 uint32_t amdgpu_amdkfd_get_asic_rev_id(struct kgd_dev *kgd);
 int amdgpu_amdkfd_get_noretry(struct kgd_dev *kgd);
 uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev 
*src);
+uint8_t amdgpu_amdkfd_get_xgmi_num_links(struct kgd_dev *dst, struct kgd_dev 
*src);
 
 /* Read user wptr from a specified user address space with page fault
  * disabled. The memory must be pinned and mapped to the hardware when
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
index 8567d5d77346..258cf86b32f6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -486,6 +486,18 @@ int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev,
return  -EINVAL;
 }
 
+int amdgpu_xgmi_get_num_links(struct amdgpu_device *adev,
+   struct amdgpu_device *peer_adev)
+{
+   struct psp_xgmi_topology_info *top = >psp.xgmi_context.top_info;
+   int i;
+
+   for (i = 0 ; i < top->num_nodes; ++i)
+   if (top->nodes[i].node_id == peer_adev->gmc.xgmi.node_id)
+   return top->nodes[i].num_links;
+   return  -EINVAL;
+}
+
 int amdgpu_xgmi_add_device(struct amdgpu_device *adev)
 {
struct psp_xgmi_topology_info *top_info;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
index 12969c0830d5..d2189bf7d428 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
@@ -59,6 +59,8 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev);
 int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate);
 int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev,
struct amdgpu_device *peer_adev);
+int amdgpu_xgmi_get_num_links(struct amdgpu_device *adev,
+   struct amdgpu_device *peer_adev);
 uint64_t amdgpu_xgmi_get_relative_phy_addr(struct amdgpu_device *adev,
   uint64_t addr);
 static inline bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index c6b02aee4993..75047b77649b 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -1034,8 +1034,8 @@ static int kfd_parse_subtype_iolink(struct 
crat_subtype_iolink *iolink,
 
props->min_latency = iolink->minimum_latency;
props->max_latency = iolink->maximum_latency;
-   props->min_bandwidth = iolink->minimum_bandwidth_mbs;
-   props->max_bandwidth = iolink->maximum_bandwidth_mbs;
+   props->min_bandwidth = iolink->minimum_bandwidth;
+   props->max_bandwidth = iolink->maximum_bandwidth;
props->rec_transfer_size =
iolink->recommended_transfer_size;
 
@@ -1989,6 

Re: [PATCH 09/10] drm/amdkfd: partially actual_loc removed

2021-06-21 Thread Felix Kuehling

On 2021-06-21 12:04 p.m., Alex Sierra wrote:

actual_loc should not be used anymore, as pranges
could have mixed locations (VRAM & SYSRAM) at the
same time.

Signed-off-by: Alex Sierra 
---
  drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 12 +---
  drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 71 ++--
  2 files changed, 29 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index f71f8d7e2b72..acb9f64577a0 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -501,12 +501,6 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t 
best_loc,
struct amdgpu_device *adev;
int r = 0;
  
-	if (prange->actual_loc == best_loc) {

-   pr_debug("svms 0x%p [0x%lx 0x%lx] already on best_loc 0x%x\n",
-prange->svms, prange->start, prange->last, best_loc);
-   return 0;
-   }
-
adev = svm_range_get_adev_by_id(prange, best_loc);
if (!adev) {
pr_debug("failed to get device by id 0x%x\n", best_loc);
@@ -791,11 +785,7 @@ int
  svm_migrate_to_vram(struct svm_range *prange, uint32_t best_loc,
struct mm_struct *mm)
  {
-   if  (!prange->actual_loc)
-   return svm_migrate_ram_to_vram(prange, best_loc, mm);
-   else
-   return svm_migrate_vram_to_vram(prange, best_loc, mm);
-
+   return svm_migrate_ram_to_vram(prange, best_loc, mm);


Can you remove svm_migrate_vram_to_vram in this case? I guess we're 
relying on the svm_range_prefault call in svm_migrate_ram_to_vram now to 
migrate VRAM in a different XGMI hive to system memory now. But 
eventually we want to get rid of that pre-fault hack.




  }
  
  /**

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 3b05bc270732..ebc1ae7e5193 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1421,42 +1421,38 @@ static int svm_range_validate_and_map(struct mm_struct 
*mm,
  
  	svm_range_reserve_bos();
  
-	if (!prange->actual_loc) {

-   p = container_of(prange->svms, struct kfd_process, svms);
-   owner = kfd_svm_page_owner(p, find_first_bit(ctx.bitmap,
-   MAX_GPU_INSTANCE));
-   for_each_set_bit(idx, ctx.bitmap, MAX_GPU_INSTANCE) {
-   if (kfd_svm_page_owner(p, idx) != owner) {
-   owner = NULL;
-   break;
-   }
-   }
-   r = amdgpu_hmm_range_get_pages(>notifier, mm, NULL,
-  prange->start << PAGE_SHIFT,
-  prange->npages, _range,
-  false, true, owner);
-   if (r) {
-   pr_debug("failed %d to get svm range pages\n", r);
-   goto unreserve_out;
-   }
-
-   r = svm_range_dma_map(prange, ctx.bitmap,
- hmm_range->hmm_pfns);
-   if (r) {
-   pr_debug("failed %d to dma map range\n", r);
-   goto unreserve_out;
+   p = container_of(prange->svms, struct kfd_process, svms);
+   owner = kfd_svm_page_owner(p, find_first_bit(ctx.bitmap,
+   MAX_GPU_INSTANCE));
+   for_each_set_bit(idx, ctx.bitmap, MAX_GPU_INSTANCE) {
+   if (kfd_svm_page_owner(p, idx) != owner) {
+   owner = NULL;
+   break;
}
+   }
+   r = amdgpu_hmm_range_get_pages(>notifier, mm, NULL,
+  prange->start << PAGE_SHIFT,
+  prange->npages, _range,
+  false, true, owner);
+   if (r) {
+   pr_debug("failed %d to get svm range pages\n", r);
+   goto unreserve_out;
+   }
  
-		prange->validated_once = true;

+   r = svm_range_dma_map(prange, ctx.bitmap,
+ hmm_range->hmm_pfns);
+   if (r) {
+   pr_debug("failed %d to dma map range\n", r);
+   goto unreserve_out;
}
  
+	prange->validated_once = true;

+
svm_range_lock(prange);
-   if (!prange->actual_loc) {
-   if (amdgpu_hmm_range_get_pages_done(hmm_range)) {
-   pr_debug("hmm update the range, need validate again\n");
-   r = -EAGAIN;
-   goto unlock_out;
-   }
+   if (amdgpu_hmm_range_get_pages_done(hmm_range)) {
+   pr_debug("hmm update the range, need validate again\n");
+   r = -EAGAIN;
+   goto unlock_out;


IMO, this is the most 

[PATCH 36/43] drm/amdgpu: Nerf buff

2021-06-21 Thread Luben Tuikov
buff --> buf. Essentially buffer abbreviates to
buf, remove 1/2 of it, or just the iron part, as
opposed to just the Er,

Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Signed-off-by: Luben Tuikov 
Reviewed-by: Alexander Deucher 
---
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c| 98 +--
 1 file changed, 49 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 21e1e59e4857ff..8b60fba9f835e6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -117,10 +117,10 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device 
*adev,
return true;
 }
 
-static void __encode_table_header_to_buff(struct 
amdgpu_ras_eeprom_table_header *hdr,
- unsigned char *buff)
+static void __encode_table_header_to_buf(struct amdgpu_ras_eeprom_table_header 
*hdr,
+unsigned char *buf)
 {
-   uint32_t *pp = (uint32_t *) buff;
+   uint32_t *pp = (uint32_t *) buf;
 
pp[0] = cpu_to_le32(hdr->header);
pp[1] = cpu_to_le32(hdr->version);
@@ -129,10 +129,10 @@ static void __encode_table_header_to_buff(struct 
amdgpu_ras_eeprom_table_header
pp[4] = cpu_to_le32(hdr->checksum);
 }
 
-static void __decode_table_header_from_buff(struct 
amdgpu_ras_eeprom_table_header *hdr,
- unsigned char *buff)
+static void __decode_table_header_from_buf(struct 
amdgpu_ras_eeprom_table_header *hdr,
+  unsigned char *buf)
 {
-   uint32_t *pp = (uint32_t *)buff;
+   u32 *pp = (uint32_t *) buf;
 
hdr->header   = le32_to_cpu(pp[0]);
hdr->version  = le32_to_cpu(pp[1]);
@@ -142,18 +142,18 @@ static void __decode_table_header_from_buff(struct 
amdgpu_ras_eeprom_table_heade
 }
 
 static int __write_table_header(struct amdgpu_ras_eeprom_control *control,
-   unsigned char *buff)
+   unsigned char *buf)
 {
int ret = 0;
struct amdgpu_device *adev = to_amdgpu_device(control);
 
-   __encode_table_header_to_buff(>tbl_hdr, buff);
+   __encode_table_header_to_buf(>tbl_hdr, buf);
 
/* i2c may be unstable in gpu reset */
down_read(>reset_sem);
ret = amdgpu_eeprom_write(>pm.smu_i2c,
  control->i2c_address + RAS_HDR_START,
- buff, RAS_TABLE_HEADER_SIZE);
+ buf, RAS_TABLE_HEADER_SIZE);
up_read(>reset_sem);
 
if (ret < 1)
@@ -240,15 +240,15 @@ static int amdgpu_ras_eeprom_correct_header_tag(
struct amdgpu_ras_eeprom_control *control,
uint32_t header)
 {
-   unsigned char buff[RAS_TABLE_HEADER_SIZE];
+   unsigned char buf[RAS_TABLE_HEADER_SIZE];
struct amdgpu_ras_eeprom_table_header *hdr = >tbl_hdr;
int ret = 0;
 
-   memset(buff, 0, RAS_TABLE_HEADER_SIZE);
+   memset(buf, 0, RAS_TABLE_HEADER_SIZE);
 
mutex_lock(>tbl_mutex);
hdr->header = header;
-   ret = __write_table_header(control, buff);
+   ret = __write_table_header(control, buf);
mutex_unlock(>tbl_mutex);
 
return ret;
@@ -256,7 +256,7 @@ static int amdgpu_ras_eeprom_correct_header_tag(
 
 int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
 {
-   unsigned char buff[RAS_TABLE_HEADER_SIZE] = { 0 };
+   unsigned char buf[RAS_TABLE_HEADER_SIZE] = { 0 };
struct amdgpu_ras_eeprom_table_header *hdr = >tbl_hdr;
int ret = 0;
 
@@ -269,7 +269,7 @@ int amdgpu_ras_eeprom_reset_table(struct 
amdgpu_ras_eeprom_control *control)
 
__update_tbl_checksum(control, NULL, 0);
control->next_addr = RAS_RECORD_START;
-   ret = __write_table_header(control, buff);
+   ret = __write_table_header(control, buf);
 
mutex_unlock(>tbl_mutex);
 
@@ -282,7 +282,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control 
*control,
 {
int ret = 0;
struct amdgpu_device *adev = to_amdgpu_device(control);
-   unsigned char buff[RAS_TABLE_HEADER_SIZE] = { 0 };
+   unsigned char buf[RAS_TABLE_HEADER_SIZE] = { 0 };
struct amdgpu_ras_eeprom_table_header *hdr = >tbl_hdr;
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
 
@@ -303,13 +303,13 @@ int amdgpu_ras_eeprom_init(struct 
amdgpu_ras_eeprom_control *control,
/* Read/Create table header from EEPROM address 0 */
ret = amdgpu_eeprom_read(>pm.smu_i2c,
 control->i2c_address + RAS_HDR_START,
-buff, RAS_TABLE_HEADER_SIZE);
+buf, RAS_TABLE_HEADER_SIZE);
if (ret < 1) {
DRM_ERROR("Failed to read EEPROM table header, ret:%d", ret);
return 

[PATCH 37/43] drm/amdgpu: Some renames

2021-06-21 Thread Luben Tuikov
Qualify with "ras_". Use kernel's own--don't
redefine your own.

Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Signed-off-by: Luben Tuikov 
Reviewed-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c   | 16 +-
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c| 30 +--
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h| 25 
 drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c   |  2 +-
 4 files changed, 43 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index c7ad90483f21d3..cd2fce8bbcab87 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -1818,11 +1818,11 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device 
*adev)
 
control = >eeprom_control;
data = con->eh_data;
-   save_count = data->count - control->num_recs;
+   save_count = data->count - control->ras_num_recs;
/* only new entries are saved */
if (save_count > 0) {
if (amdgpu_ras_eeprom_write(control,
-   >bps[control->num_recs],
+   >bps[control->ras_num_recs],
save_count)) {
dev_err(adev->dev, "Failed to save EEPROM table data!");
return -EIO;
@@ -1846,18 +1846,18 @@ static int amdgpu_ras_load_bad_pages(struct 
amdgpu_device *adev)
int ret;
 
/* no bad page record, skip eeprom access */
-   if (control->num_recs == 0 || amdgpu_bad_page_threshold == 0)
+   if (control->ras_num_recs == 0 || amdgpu_bad_page_threshold == 0)
return 0;
 
-   bps = kcalloc(control->num_recs, sizeof(*bps), GFP_KERNEL);
+   bps = kcalloc(control->ras_num_recs, sizeof(*bps), GFP_KERNEL);
if (!bps)
return -ENOMEM;
 
-   ret = amdgpu_ras_eeprom_read(control, bps, control->num_recs);
+   ret = amdgpu_ras_eeprom_read(control, bps, control->ras_num_recs);
if (ret)
dev_err(adev->dev, "Failed to load EEPROM table records!");
else
-   ret = amdgpu_ras_add_bad_pages(adev, bps, control->num_recs);
+   ret = amdgpu_ras_add_bad_pages(adev, bps, 
control->ras_num_recs);
 
kfree(bps);
return ret;
@@ -1974,13 +1974,13 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
if (exc_err_limit || ret)
goto free;
 
-   if (con->eeprom_control.num_recs) {
+   if (con->eeprom_control.ras_num_recs) {
ret = amdgpu_ras_load_bad_pages(adev);
if (ret)
goto free;
 
if (adev->smu.ppt_funcs && 
adev->smu.ppt_funcs->send_hbm_bad_pages_num)
-   adev->smu.ppt_funcs->send_hbm_bad_pages_num(>smu, 
con->eeprom_control.num_recs);
+   adev->smu.ppt_funcs->send_hbm_bad_pages_num(>smu, 
con->eeprom_control.ras_num_recs);
}
 
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 8b60fba9f835e6..34da00ef8369bb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -246,10 +246,10 @@ static int amdgpu_ras_eeprom_correct_header_tag(
 
memset(buf, 0, RAS_TABLE_HEADER_SIZE);
 
-   mutex_lock(>tbl_mutex);
+   mutex_lock(>ras_tbl_mutex);
hdr->header = header;
ret = __write_table_header(control, buf);
-   mutex_unlock(>tbl_mutex);
+   mutex_unlock(>ras_tbl_mutex);
 
return ret;
 }
@@ -260,7 +260,7 @@ int amdgpu_ras_eeprom_reset_table(struct 
amdgpu_ras_eeprom_control *control)
struct amdgpu_ras_eeprom_table_header *hdr = >tbl_hdr;
int ret = 0;
 
-   mutex_lock(>tbl_mutex);
+   mutex_lock(>ras_tbl_mutex);
 
hdr->header = RAS_TABLE_HDR_VAL;
hdr->version = RAS_TABLE_VER;
@@ -271,7 +271,7 @@ int amdgpu_ras_eeprom_reset_table(struct 
amdgpu_ras_eeprom_control *control)
control->next_addr = RAS_RECORD_START;
ret = __write_table_header(control, buf);
 
-   mutex_unlock(>tbl_mutex);
+   mutex_unlock(>ras_tbl_mutex);
 
return ret;
 
@@ -298,7 +298,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control 
*control,
if (!__get_eeprom_i2c_addr(adev, control))
return -EINVAL;
 
-   mutex_init(>tbl_mutex);
+   mutex_init(>ras_tbl_mutex);
 
/* Read/Create table header from EEPROM address 0 */
ret = amdgpu_eeprom_read(>pm.smu_i2c,
@@ -312,17 +312,17 @@ int amdgpu_ras_eeprom_init(struct 
amdgpu_ras_eeprom_control *control,
__decode_table_header_from_buf(hdr, buf);
 
if (hdr->header == RAS_TABLE_HDR_VAL) {
-   control->num_recs = (hdr->tbl_size - RAS_TABLE_HEADER_SIZE) /
+   

[PATCH 38/43] drm/amdgpu: Get rid of test function

2021-06-21 Thread Luben Tuikov
The code is now tested from userspace.
Remove already macroed out test function.

Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Signed-off-by: Luben Tuikov 
Reviewed-by: Alexander Deucher 
---
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c| 33 ---
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h|  2 --
 2 files changed, 35 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 34da00ef8369bb..7522d2ca5b03fc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -572,36 +572,3 @@ inline uint32_t amdgpu_ras_eeprom_max_record_count(void)
 {
return RAS_MAX_RECORD_COUNT;
 }
-
-/* Used for testing if bugs encountered */
-#if 0
-void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control)
-{
-   int i;
-   struct eeprom_table_record *recs = kcalloc(1, sizeof(*recs), 
GFP_KERNEL);
-
-   if (!recs)
-   return;
-
-   for (i = 0; i < 1 ; i++) {
-   recs[i].address = 0xdeadbeef;
-   recs[i].retired_page = i;
-   }
-
-   if (!amdgpu_ras_eeprom_write(control, recs, 1)) {
-
-   memset(recs, 0, sizeof(*recs) * 1);
-
-   control->next_addr = RAS_RECORD_START;
-
-   if (!amdgpu_ras_eeprom_read(control, recs)) {
-   for (i = 0; i < 1; i++)
-   DRM_INFO("rec.address :0x%llx, rec.retired_page 
:%llu",
-recs[i].address, recs[i].retired_page);
-   } else
-   DRM_ERROR("Failed in reading from table");
-
-   } else
-   DRM_ERROR("Failed in writing to table");
-}
-#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
index 9e1e7656b7bc2a..67a7ec3e6c2296 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
@@ -103,6 +103,4 @@ int amdgpu_ras_eeprom_write(struct 
amdgpu_ras_eeprom_control *control,
 
 inline uint32_t amdgpu_ras_eeprom_max_record_count(void);
 
-void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control);
-
 #endif // _AMDGPU_RAS_EEPROM_H
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 42/43] drm/amdgpu: Use a single loop

2021-06-21 Thread Luben Tuikov
In smu_v11_0_i2c_transmit() use a single loop to
transmit bytes, instead of two nested loops.

Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Signed-off-by: Luben Tuikov 
Reviewed-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 72 ++
 1 file changed, 34 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c 
b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index 7f48ee020bc03e..751ea2517c4380 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -243,49 +243,45 @@ static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter 
*control,
/* Clear status bits */
smu_v11_0_i2c_clear_status(control);
 
-
timeout_counter = jiffies + msecs_to_jiffies(20);
 
while (numbytes > 0) {
reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS);
-   if (REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)) {
-   do {
-   reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, 
DAT, data[bytes_sent]);
-
-   /* Final message, final byte, must
-* generate a STOP, to release the
-* bus, i.e. don't hold SCL low.
-*/
-   if (numbytes == 1 && i2c_flag & I2C_M_STOP)
-   reg = REG_SET_FIELD(reg,
-   
CKSVII2C_IC_DATA_CMD,
-   STOP, 1);
-
-   if (bytes_sent == 0 && i2c_flag & I2C_X_RESTART)
-   reg = REG_SET_FIELD(reg,
-   
CKSVII2C_IC_DATA_CMD,
-   RESTART, 1);
-
-   /* Write */
-   reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, 
CMD, 0);
-   WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, 
reg);
-
-   /* Record that the bytes were transmitted */
-   bytes_sent++;
-   numbytes--;
-
-   reg = RREG32_SOC15(SMUIO, 0, 
mmCKSVII2C_IC_STATUS);
-
-   } while (numbytes &&  REG_GET_FIELD(reg, 
CKSVII2C_IC_STATUS, TFNF));
-   }
+   if (!REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)) {
+   /*
+* We waited for too long for the transmission
+* FIFO to become not-full.  Exit the loop
+* with error.
+*/
+   if (time_after(jiffies, timeout_counter)) {
+   ret |= I2C_SW_TIMEOUT;
+   goto Err;
+   }
+   } else {
+   reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT,
+   data[bytes_sent]);
 
-   /*
-* We waited too long for the transmission FIFO to become 
not-full.
-* Exit the loop with error.
-*/
-   if (time_after(jiffies, timeout_counter)) {
-   ret |= I2C_SW_TIMEOUT;
-   goto Err;
+   /* Final message, final byte, must generate a
+* STOP to release the bus, i.e. don't hold
+* SCL low.
+*/
+   if (numbytes == 1 && i2c_flag & I2C_M_STOP)
+   reg = REG_SET_FIELD(reg,
+   CKSVII2C_IC_DATA_CMD,
+   STOP, 1);
+
+   if (bytes_sent == 0 && i2c_flag & I2C_X_RESTART)
+   reg = REG_SET_FIELD(reg,
+   CKSVII2C_IC_DATA_CMD,
+   RESTART, 1);
+
+   /* Write */
+   reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 0);
+   WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg);
+
+   /* Record that the bytes were transmitted */
+   bytes_sent++;
+   numbytes--;
}
}
 
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 32/43] drm/amdgpu: Return result fix in RAS

2021-06-21 Thread Luben Tuikov
The low level EEPROM write method, doesn't return
1, but the number of bytes written. Thus do not
compare to 1, instead, compare to greater than 0
for success.

Other cleanup: if the lower layers returned
-errno, then return that, as opposed to
overwriting the error code with one-fits-all
-EINVAL. For instance, some return -EAGAIN.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Reviewed-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c|  3 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c   | 22 +++
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c|  2 +-
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c|  3 +--
 4 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
index a5a87affedabf1..a4815af111ed12 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
@@ -105,8 +105,7 @@ static int __amdgpu_eeprom_xfer(struct i2c_adapter 
*i2c_adap, u32 eeprom_addr,
int r;
u16 len;
 
-   r = 0;
-   for ( ; buf_size > 0;
+   for (r = 0; buf_size > 0;
  buf_size -= len, eeprom_addr += len, eeprom_buf += len) {
/* Set the EEPROM address we want to write to/read from.
 */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index a9af6d0a2ed6bc..64054a825b7421 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -355,8 +355,9 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file 
*f,
  * to see which blocks support RAS on a particular asic.
  *
  */
-static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user 
*buf,
-   size_t size, loff_t *pos)
+static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f,
+const char __user *buf,
+size_t size, loff_t *pos)
 {
struct amdgpu_device *adev = (struct amdgpu_device 
*)file_inode(f)->i_private;
struct ras_debug_if data;
@@ -370,7 +371,7 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file 
*f, const char __user *
 
ret = amdgpu_ras_debugfs_ctrl_parse_data(f, buf, size, pos, );
if (ret)
-   return -EINVAL;
+   return ret;
 
if (data.op == 3) {
ret = amdgpu_reserve_page_direct(adev, data.inject.address);
@@ -439,21 +440,24 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file 
*f, const char __user *
  * will reset EEPROM table to 0 entries.
  *
  */
-static ssize_t amdgpu_ras_debugfs_eeprom_write(struct file *f, const char 
__user *buf,
-   size_t size, loff_t *pos)
+static ssize_t amdgpu_ras_debugfs_eeprom_write(struct file *f,
+  const char __user *buf,
+  size_t size, loff_t *pos)
 {
struct amdgpu_device *adev =
(struct amdgpu_device *)file_inode(f)->i_private;
int ret;
 
ret = amdgpu_ras_eeprom_reset_table(
-   &(amdgpu_ras_get_context(adev)->eeprom_control));
+   &(amdgpu_ras_get_context(adev)->eeprom_control));
 
-   if (ret == 1) {
+   if (ret > 0) {
+   /* Something was written to EEPROM.
+*/
amdgpu_ras_get_context(adev)->flags = RAS_DEFAULT_FLAGS;
return size;
} else {
-   return -EIO;
+   return ret;
}
 }
 
@@ -1994,7 +1998,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
kfree(*data);
con->eh_data = NULL;
 out:
-   dev_warn(adev->dev, "Failed to initialize ras recovery!\n");
+   dev_warn(adev->dev, "Failed to initialize ras recovery! (%d)\n", ret);
 
/*
 * Except error threshold exceeding case, other failure cases in this
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 17cea35275e46c..dc48c556398039 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -335,7 +335,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control 
*control,
ret = amdgpu_ras_eeprom_reset_table(control);
}
 
-   return ret == 1 ? 0 : -EIO;
+   return ret > 0 ? 0 : -EIO;
 }
 
 static void __encode_table_record_to_buff(struct amdgpu_ras_eeprom_control 
*control,
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c 
b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index 65035256756679..7f48ee020bc03e 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -222,7 +222,7 @@ static uint32_t 

[PATCH 43/43] drm/amdgpu: Correctly disable the I2C IP block

2021-06-21 Thread Luben Tuikov
On long transfers to the EEPROM device,
i.e. write, it is observed that the driver aborts
the transfer.

The reason for this is that the driver isn't
patient enough--the IC_STATUS register's contents
is 0x27, which is MST_ACTIVITY | TFE | TFNF |
ACTIVITY. That is, while the transmission FIFO is
empty, we, the I2C master device, are still
driving the bus.

Implement the correct procedure to disable
the block, as described in the DesignWare I2C
Databook, section 3.8.3 Disabling DW_apb_i2c on
page 56. Now there are no premature aborts on long
data transfers.

Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 80 +-
 1 file changed, 62 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c 
b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index 751ea2517c4380..7d74d6204d8d0a 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -54,12 +54,48 @@ static void smu_v11_0_i2c_set_clock_gating(struct 
i2c_adapter *control, bool en)
WREG32_SOC15(SMUIO, 0, mmSMUIO_PWRMGT, reg);
 }
 
+/* The T_I2C_POLL_US is defined as follows:
+ *
+ * "Define a timer interval (t_i2c_poll) equal to 10 times the
+ *  signalling period for the highest I2C transfer speed used in the
+ *  system and supported by DW_apb_i2c. For instance, if the highest
+ *  I2C data transfer mode is 400 kb/s, then t_i2c_poll is 25 us."  --
+ * DesignWare DW_apb_i2c Databook, Version 1.21a, section 3.8.3.1,
+ * page 56, with grammar and syntax corrections.
+ *
+ * Vcc for our device is at 1.8V which puts it at 400 kHz,
+ * see Atmel AT24CM02 datasheet, section 8.3 DC Characteristics table, page 14.
+ *
+ * The procedure to disable the IP block is described in section
+ * 3.8.3 Disabling DW_apb_i2c on page 56.
+ */
+#define I2C_SPEED_MODE_FAST 2
+#define T_I2C_POLL_US   25
+#define I2C_MAX_T_POLL_COUNT1000
 
-static void smu_v11_0_i2c_enable(struct i2c_adapter *control, bool enable)
+static int smu_v11_0_i2c_enable(struct i2c_adapter *control, bool enable)
 {
struct amdgpu_device *adev = to_amdgpu_device(control);
 
WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE, enable ? 1 : 0);
+
+   if (!enable) {
+   int ii;
+
+   for (ii = I2C_MAX_T_POLL_COUNT; ii > 0; ii--) {
+   u32 en_stat = RREG32_SOC15(SMUIO,
+  0,
+  mmCKSVII2C_IC_ENABLE_STATUS);
+   if (REG_GET_FIELD(en_stat, CKSVII2C_IC_ENABLE_STATUS, 
IC_EN))
+   udelay(T_I2C_POLL_US);
+   else
+   return I2C_OK;
+   }
+
+   return I2C_ABORT;
+   }
+
+   return I2C_OK;
 }
 
 static void smu_v11_0_i2c_clear_status(struct i2c_adapter *control)
@@ -81,8 +117,13 @@ static void smu_v11_0_i2c_configure(struct i2c_adapter 
*control)
reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_RESTART_EN, 1);
reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_MASTER, 0);
reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_SLAVE, 0);
-   /* Standard mode */
-   reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MAX_SPEED_MODE, 2);
+   /* The values of IC_MAX_SPEED_MODE are,
+* 1: standard mode, 0 - 100 Kb/s,
+* 2: fast mode, <= 400 Kb/s, or fast mode plus, <= 1000 Kb/s,
+* 3: high speed mode, <= 3.4 Mb/s.
+*/
+   reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MAX_SPEED_MODE,
+   I2C_SPEED_MODE_FAST);
reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MASTER_MODE, 1);
 
WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_CON, reg);
@@ -404,7 +445,6 @@ static void smu_v11_0_i2c_abort(struct i2c_adapter *control)
DRM_DEBUG_DRIVER("I2C_Abort() Done.");
 }
 
-
 static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control)
 {
struct amdgpu_device *adev = to_amdgpu_device(control);
@@ -416,7 +456,6 @@ static bool smu_v11_0_i2c_activity_done(struct i2c_adapter 
*control)
reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, 
mmCKSVII2C_IC_ENABLE_STATUS);
reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE);
 
-
if ((REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE) == 0) &&
(REG_GET_FIELD(reg_ic_enable_status, CKSVII2C_IC_ENABLE_STATUS, 
IC_EN) == 1)) {
/*
@@ -446,6 +485,8 @@ static bool smu_v11_0_i2c_activity_done(struct i2c_adapter 
*control)
 
 static void smu_v11_0_i2c_init(struct i2c_adapter *control)
 {
+   int res;
+
/* Disable clock gating */
smu_v11_0_i2c_set_clock_gating(control, false);
 
@@ -453,7 +494,9 @@ static void smu_v11_0_i2c_init(struct i2c_adapter *control)
DRM_WARN("I2C busy !");
 
/* Disable I2C */
- 

[PATCH 35/43] drm/amdgpu: Use explicit cardinality for clarity

2021-06-21 Thread Luben Tuikov
RAS_MAX_RECORD_NUM may mean the maximum record
number, as in the maximum house number on your
street, or it may mean the maximum number of
records, as in the count of records, which is also
a number. To make this distinction whether the
number is ordinal (index) or cardinal (count),
rename this macro to RAS_MAX_RECORD_COUNT.

This makes it easy to understand what it refers
to, especially when we compute quantities such as,
how many records do we have left in the table,
especially when there are so many other numbers,
quantities and numerical macros around.

Also rename the long,
amdgpu_ras_eeprom_get_record_max_length() to the
more succinct and clear,
amdgpu_ras_eeprom_max_record_count().

When computing the threshold, which also deals
with counts, i.e. "how many", use cardinal
"max_eeprom_records_count", than the quantitative
"max_eeprom_records_len".

Simplify the logic here and there, as well.

Cc: Guchun Chen 
Cc: John Clements 
Cc: Hawking Zhang 
Cc: Alexander Deucher 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c   |  9 ++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c   | 50 ---
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c|  8 +--
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h|  2 +-
 4 files changed, 30 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 80dab0c6e19ebb..406043c9906425 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -868,11 +868,10 @@ MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = 
auto (default), 0 = legac
 module_param_named(reset_method, amdgpu_reset_method, int, 0444);
 
 /**
- * DOC: bad_page_threshold (int)
- * Bad page threshold is to specify the threshold value of faulty pages
- * detected by RAS ECC, that may result in GPU entering bad status if total
- * faulty pages by ECC exceed threshold value and leave it for user's further
- * check.
+ * DOC: bad_page_threshold (int) Bad page threshold is specifies the
+ * threshold value of faulty pages detected by RAS ECC, which may
+ * result in the GPU entering bad status when the number of total
+ * faulty pages by ECC exceeds the threshold value.
  */
 MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default 
value), 0 = disable bad page retirement)");
 module_param_named(bad_page_threshold, amdgpu_bad_page_threshold, int, 0444);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 64054a825b7421..c7ad90483f21d3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -71,8 +71,8 @@ const char *ras_block_string[] = {
 /* inject address is 52 bits */
 #defineRAS_UMC_INJECT_ADDR_LIMIT   (0x1ULL << 52)
 
-/* typical ECC bad page rate(1 bad page per 100MB VRAM) */
-#define RAS_BAD_PAGE_RATE  (100 * 1024 * 1024ULL)
+/* typical ECC bad page rate is 1 bad page per 100MB VRAM */
+#define RAS_BAD_PAGE_COVER  (100 * 1024 * 1024ULL)
 
 enum amdgpu_ras_retire_page_reservation {
AMDGPU_RAS_RETIRE_PAGE_RESERVED,
@@ -1841,27 +1841,24 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device 
*adev)
 static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev)
 {
struct amdgpu_ras_eeprom_control *control =
-   >psp.ras.ras->eeprom_control;
-   struct eeprom_table_record *bps = NULL;
-   int ret = 0;
+   >psp.ras.ras->eeprom_control;
+   struct eeprom_table_record *bps;
+   int ret;
 
/* no bad page record, skip eeprom access */
-   if (!control->num_recs || (amdgpu_bad_page_threshold == 0))
-   return ret;
+   if (control->num_recs == 0 || amdgpu_bad_page_threshold == 0)
+   return 0;
 
bps = kcalloc(control->num_recs, sizeof(*bps), GFP_KERNEL);
if (!bps)
return -ENOMEM;
 
-   if (amdgpu_ras_eeprom_read(control, bps, control->num_recs)) {
+   ret = amdgpu_ras_eeprom_read(control, bps, control->num_recs);
+   if (ret)
dev_err(adev->dev, "Failed to load EEPROM table records!");
-   ret = -EIO;
-   goto out;
-   }
-
-   ret = amdgpu_ras_add_bad_pages(adev, bps, control->num_recs);
+   else
+   ret = amdgpu_ras_add_bad_pages(adev, bps, control->num_recs);
 
-out:
kfree(bps);
return ret;
 }
@@ -1901,11 +1898,9 @@ static bool amdgpu_ras_check_bad_page(struct 
amdgpu_device *adev,
 }
 
 static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev,
-   uint32_t max_length)
+ uint32_t max_count)
 {
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
-   int tmp_threshold = amdgpu_bad_page_threshold;
-   u64 val;
 
/*
 * 

[PATCH 34/43] drm/amdgpu: Simplify RAS EEPROM checksum calculations

2021-06-21 Thread Luben Tuikov
Rename update_table_header() to
write_table_header() as this function is actually
writing it to EEPROM.

Use kernel types; use u8 to carry around the
checksum, in order to take advantage of arithmetic
modulo 8-bits (256).

Tidy up to 80 columns.

When updating the checksum, just recalculate the
whole thing.

Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c| 98 +--
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h|  2 +-
 2 files changed, 50 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 7d0f9e1e62dc4f..54ef31594accd9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -141,8 +141,8 @@ static void __decode_table_header_from_buff(struct 
amdgpu_ras_eeprom_table_heade
hdr->checksum = le32_to_cpu(pp[4]);
 }
 
-static int __update_table_header(struct amdgpu_ras_eeprom_control *control,
-unsigned char *buff)
+static int __write_table_header(struct amdgpu_ras_eeprom_control *control,
+   unsigned char *buff)
 {
int ret = 0;
struct amdgpu_device *adev = to_amdgpu_device(control);
@@ -162,69 +162,74 @@ static int __update_table_header(struct 
amdgpu_ras_eeprom_control *control,
return ret;
 }
 
-static uint32_t  __calc_hdr_byte_sum(struct amdgpu_ras_eeprom_control *control)
+static u8 __calc_hdr_byte_sum(const struct amdgpu_ras_eeprom_control *control)
 {
int i;
-   uint32_t tbl_sum = 0;
+   u8 hdr_sum = 0;
+   u8  *p;
+   size_t sz;
 
/* Header checksum, skip checksum field in the calculation */
-   for (i = 0; i < sizeof(control->tbl_hdr) - 
sizeof(control->tbl_hdr.checksum); i++)
-   tbl_sum += *(((unsigned char *)>tbl_hdr) + i);
+   sz = sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum);
+   p = (u8 *) >tbl_hdr;
+   for (i = 0; i < sz; i++, p++)
+   hdr_sum += *p;
 
-   return tbl_sum;
+   return hdr_sum;
 }
 
-static uint32_t  __calc_recs_byte_sum(struct eeprom_table_record *records,
- int num)
+static u8 __calc_recs_byte_sum(const struct eeprom_table_record *record,
+  const int num)
 {
int i, j;
-   uint32_t tbl_sum = 0;
+   u8  tbl_sum = 0;
+
+   if (!record)
+   return 0;
 
/* Records checksum */
for (i = 0; i < num; i++) {
-   struct eeprom_table_record *record = [i];
+   u8 *p = (u8 *) [i];
 
-   for (j = 0; j < sizeof(*record); j++) {
-   tbl_sum += *(((unsigned char *)record) + j);
-   }
+   for (j = 0; j < sizeof(*record); j++, p++)
+   tbl_sum += *p;
}
 
return tbl_sum;
 }
 
-static inline uint32_t  __calc_tbl_byte_sum(struct amdgpu_ras_eeprom_control 
*control,
- struct eeprom_table_record *records, int num)
+static inline u8
+__calc_tbl_byte_sum(struct amdgpu_ras_eeprom_control *control,
+   struct eeprom_table_record *records, int num)
 {
-   return __calc_hdr_byte_sum(control) + __calc_recs_byte_sum(records, 
num);
+   return __calc_hdr_byte_sum(control) +
+   __calc_recs_byte_sum(records, num);
 }
 
-/* Checksum = 256 -((sum of all table entries) mod 256) */
 static void __update_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
- struct eeprom_table_record *records, int num,
- uint32_t old_hdr_byte_sum)
+ struct eeprom_table_record *records, int num)
 {
-   /*
-* This will update the table sum with new records.
-*
-* TODO: What happens when the EEPROM table is to be wrapped around
-* and old records from start will get overridden.
-*/
-
-   /* need to recalculate updated header byte sum */
-   control->tbl_byte_sum -= old_hdr_byte_sum;
-   control->tbl_byte_sum += __calc_tbl_byte_sum(control, records, num);
+   u8 v;
 
-   control->tbl_hdr.checksum = 256 - (control->tbl_byte_sum % 256);
+   control->tbl_byte_sum = __calc_tbl_byte_sum(control, records, num);
+   /* Avoid 32-bit sign extension. */
+   v = -control->tbl_byte_sum;
+   control->tbl_hdr.checksum = v;
 }
 
-/* table sum mod 256 + checksum must equals 256 */
-static bool __validate_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
-   struct eeprom_table_record *records, int num)
+static bool __verify_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
+ struct eeprom_table_record *records,
+ int num)
 

[PATCH 40/43] drm/amdgpu: RAS EEPROM table is now in debugfs

2021-06-21 Thread Luben Tuikov
Add "ras_eeprom_size" file in debugfs, which
reports the maximum size allocated to the RAS
table in EEROM, as the number of bytes and the
number of records it could store. For instance,

$cat /sys/kernel/debug/dri/0/ras/ras_eeprom_size
262144 bytes or 10921 records
$_

Add "ras_eeprom_table" file in debugfs, which
dumps the RAS table stored EEPROM, in a formatted
way. For instance,

$cat ras_eeprom_table
 SignatureVersion  FirstOffs   Size   Checksum
0x414D4452 0x0001 0x0014 0x00EC 0x00DA
Index  Offset ErrType Bank/CU  TimeStamp  Offs/Addr MemChl MCUMCID  
  RetiredPage
0 0x00014  ue0x00 0x607608DC 0x   0x000x00 
0x
1 0x0002C  ue0x00 0x607608DC 0x1000   0x000x00 
0x0001
2 0x00044  ue0x00 0x607608DC 0x2000   0x000x00 
0x0002
3 0x0005C  ue0x00 0x607608DC 0x3000   0x000x00 
0x0003
4 0x00074  ue0x00 0x607608DC 0x4000   0x000x00 
0x0004
5 0x0008C  ue0x00 0x607608DC 0x5000   0x000x00 
0x0005
6 0x000A4  ue0x00 0x607608DC 0x6000   0x000x00 
0x0006
7 0x000BC  ue0x00 0x607608DC 0x7000   0x000x00 
0x0007
8 0x000D4  ue0x00 0x607608DD 0x8000   0x000x00 
0x0008
$_

Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: John Clements 
Cc: Hawking Zhang 
Cc: Xinhui Pan 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c   |  12 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h   |   1 +
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c| 241 +-
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h|  10 +-
 4 files changed, 252 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index f15f8ab5b9affb..edf4c02d075f48 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -404,9 +404,9 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f,
/* umc ce/ue error injection for a bad page is not allowed */
if ((data.head.block == AMDGPU_RAS_BLOCK__UMC) &&
amdgpu_ras_check_bad_page(adev, data.inject.address)) {
-   dev_warn(adev->dev, "RAS WARN: 0x%llx has been marked "
-   "as bad before error injection!\n",
-   data.inject.address);
+   dev_warn(adev->dev, "RAS WARN: inject: 0x%llx has "
+"already been marked as bad!\n",
+data.inject.address);
break;
}
 
@@ -1301,6 +1301,12 @@ static struct dentry 
*amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *
   >bad_page_cnt_threshold);
debugfs_create_x32("ras_hw_enabled", 0444, dir, >ras_hw_enabled);
debugfs_create_x32("ras_enabled", 0444, dir, >ras_enabled);
+   debugfs_create_file("ras_eeprom_size", S_IRUGO, dir, adev,
+   _ras_debugfs_eeprom_size_ops);
+   con->de_ras_eeprom_table = debugfs_create_file("ras_eeprom_table",
+  S_IRUGO, dir, adev,
+  
_ras_debugfs_eeprom_table_ops);
+   amdgpu_ras_debugfs_set_ret_size(>eeprom_control);
 
/*
 * After one uncorrectable error happens, usually GPU recovery will
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
index 256cea5d34f2b6..283afd791db107 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
@@ -318,6 +318,7 @@ struct amdgpu_ras {
/* sysfs */
struct device_attribute features_attr;
struct bin_attribute badpages_attr;
+   struct dentry *de_ras_eeprom_table;
/* block array */
struct ras_manager *objs;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index dc4a845a32404c..677e379f5fb5e9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -27,6 +27,8 @@
 #include 
 #include "atom.h"
 #include "amdgpu_eeprom.h"
+#include 
+#include 
 
 #define EEPROM_I2C_MADDR_VEGA20 0x0
 #define EEPROM_I2C_MADDR_ARCTURUS   0x4
@@ -70,6 +72,13 @@
 #define RAS_OFFSET_TO_INDEX(_C, _O) (((_O) - \
  (_C)->ras_record_offset) / 
RAS_TABLE_RECORD_SIZE)
 
+/* Given a 0-based relative record index, 0, 1, 2, ..., etc., off
+ * of "fri", return the absolute record index off of the end of
+ * the table header.
+ */

[PATCH 39/43] drm/amdgpu: Optimize EEPROM RAS table I/O

2021-06-21 Thread Luben Tuikov
Split functionality between read and write, which
simplifies the code and exposes areas of
optimization and more or less complexity, and take
advantage of that.

Read and write the table in one go; use a separate
stage to decode or encode the data, as opposed to
on the fly, which keeps the I2C bus busy. Use a
single read/write to read/write the table or at
most two if the number of records we're
reading/writing wraps around.

Check the check-sum of a table in EEPROM on init.

Update the checksum at the same time as when
updating the table header signature, when the
threshold was increased on boot.

Take advantage of arithmetic modulo 256, that is,
use a byte!, to greatly simplify checksum
arithmetic.

Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c|  20 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h|  23 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c   |   8 +-
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c| 844 --
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h|  32 +-
 5 files changed, 620 insertions(+), 307 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
index a4815af111ed12..4c3c65a5acae9b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
@@ -176,8 +176,8 @@ static int __amdgpu_eeprom_xfer(struct i2c_adapter 
*i2c_adap, u32 eeprom_addr,
  *
  * Returns the number of bytes read/written; -errno on error.
  */
-int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 eeprom_addr,
-  u8 *eeprom_buf, u16 buf_size, bool read)
+static int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 eeprom_addr,
+ u8 *eeprom_buf, u16 buf_size, bool read)
 {
const struct i2c_adapter_quirks *quirks = i2c_adap->quirks;
u16 limit;
@@ -221,3 +221,19 @@ int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 
eeprom_addr,
return res;
}
 }
+
+int amdgpu_eeprom_read(struct i2c_adapter *i2c_adap,
+  u32 eeprom_addr, u8 *eeprom_buf,
+  u16 bytes)
+{
+   return amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, eeprom_buf, bytes,
+ true);
+}
+
+int amdgpu_eeprom_write(struct i2c_adapter *i2c_adap,
+   u32 eeprom_addr, u8 *eeprom_buf,
+   u16 bytes)
+{
+   return amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, eeprom_buf, bytes,
+ false);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h
index 966b434f0de2b7..6935adb2be1f1c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h
@@ -26,23 +26,12 @@
 
 #include 
 
-int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 eeprom_addr,
-  u8 *eeprom_buf, u16 bytes, bool read);
+int amdgpu_eeprom_read(struct i2c_adapter *i2c_adap,
+  u32 eeprom_addr, u8 *eeprom_buf,
+  u16 bytes);
 
-static inline int amdgpu_eeprom_read(struct i2c_adapter *i2c_adap,
-u32 eeprom_addr, u8 *eeprom_buf,
-u16 bytes)
-{
-   return amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, eeprom_buf, bytes,
- true);
-}
-
-static inline int amdgpu_eeprom_write(struct i2c_adapter *i2c_adap,
- u32 eeprom_addr, u8 *eeprom_buf,
- u16 bytes)
-{
-   return amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, eeprom_buf, bytes,
- false);
-}
+int amdgpu_eeprom_write(struct i2c_adapter *i2c_adap,
+   u32 eeprom_addr, u8 *eeprom_buf,
+   u16 bytes);
 
 #endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index cd2fce8bbcab87..f15f8ab5b9affb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -451,7 +451,7 @@ static ssize_t amdgpu_ras_debugfs_eeprom_write(struct file 
*f,
ret = amdgpu_ras_eeprom_reset_table(
&(amdgpu_ras_get_context(adev)->eeprom_control));
 
-   if (ret > 0) {
+   if (!ret) {
/* Something was written to EEPROM.
 */
amdgpu_ras_get_context(adev)->flags = RAS_DEFAULT_FLAGS;
@@ -1821,9 +1821,9 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev)
save_count = data->count - control->ras_num_recs;
/* only new entries are saved */
if (save_count > 0) {
-   if (amdgpu_ras_eeprom_write(control,
-   >bps[control->ras_num_recs],
-   save_count)) {
+   

[PATCH 30/43] drm/amd/pm: Simplify managed I2C transfer functions

2021-06-21 Thread Luben Tuikov
Now that we have an I2C quirk table for
SMU-managed I2C controllers, the I2C core does the
checks for us, so we don't need to do them, and so
simplify the managed I2C transfer functions.

Also, for Arcturus and Navi10, fix setting the
command type from "cmd->CmdConfig" to "cmd->Cmd".
The latter is what appears to be taking in
the enumeration I2C_CMD_... as an integer,
not a bit-flag.

For Sienna, the "Cmd" field seems to have been
eliminated, and command type and flags all live in
the "CmdConfig" field--this is left untouched.

Fix: Detect and add changing of direction
bit-flag, as this is necessary for the SMU to
detect the direction change in the 1-d array of
data it gets.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 78 ---
 .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c   | 78 ---
 .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c   | 76 --
 3 files changed, 95 insertions(+), 137 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 3286c704bd08df..dc884b719717ad 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1937,31 +1937,14 @@ static int arcturus_dpm_set_vcn_enable(struct 
smu_context *smu, bool enable)
 }
 
 static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
-struct i2c_msg *msgs, int num)
+struct i2c_msg *msg, int num_msgs)
 {
struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
struct smu_table_context *smu_table = >smu.smu_table;
struct smu_table *table = _table->driver_table;
SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
-   short available_bytes = MAX_SW_I2C_COMMANDS;
-   int i, j, r, c, num_done = 0;
-   u8 slave;
-
-   /* only support a single slave addr per transaction */
-   slave = msgs[0].addr;
-   for (i = 0; i < num; i++) {
-   if (slave != msgs[i].addr)
-   return -EINVAL;
-
-   available_bytes -= msgs[i].len;
-   if (available_bytes >= 0) {
-   num_done++;
-   } else {
-   /* This message and all the follwing won't be processed 
*/
-   available_bytes += msgs[i].len;
-   break;
-   }
-   }
+   int i, j, r, c;
+   u16 dir;
 
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
@@ -1969,33 +1952,38 @@ static int arcturus_i2c_xfer(struct i2c_adapter 
*i2c_adap,
 
req->I2CcontrollerPort = 1;
req->I2CSpeed = I2C_SPEED_FAST_400K;
-   req->SlaveAddress = slave << 1; /* 8 bit addresses */
-   req->NumCmds = MAX_SW_I2C_COMMANDS - available_bytes;;
-
-   c = 0;
-   for (i = 0; i < num_done; i++) {
-   struct i2c_msg *msg = [i];
+   req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
+   dir = msg[0].flags & I2C_M_RD;
 
-   for (j = 0; j < msg->len; j++) {
-   SwI2cCmd_t *cmd = >SwI2cCmds[c++];
+   for (c = i = 0; i < num_msgs; i++) {
+   for (j = 0; j < msg[i].len; j++, c++) {
+   SwI2cCmd_t *cmd = >SwI2cCmds[c];
 
if (!(msg[i].flags & I2C_M_RD)) {
/* write */
-   cmd->CmdConfig |= I2C_CMD_WRITE;
-   cmd->RegisterAddr = msg->buf[j];
+   cmd->Cmd = I2C_CMD_WRITE;
+   cmd->RegisterAddr = msg[i].buf[j];
+   }
+
+   if ((dir ^ msg[i].flags) & I2C_M_RD) {
+   /* The direction changes.
+*/
+   dir = msg[i].flags & I2C_M_RD;
+   cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
}
 
+   req->NumCmds++;
+
/*
 * Insert STOP if we are at the last byte of either last
 * message for the transaction or the client explicitly
 * requires a STOP at this particular message.
 */
-   if ((j == msg->len -1 ) &&
-   ((i == num_done - 1) || (msg[i].flags & 
I2C_M_STOP)))
+   if ((j == msg[i].len - 1) &&
+   ((i == num_msgs - 1) || (msg[i].flags & 
I2C_M_STOP))) {
+   cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
-
-   

[PATCH 41/43] drm/amdgpu: Fix koops when accessing RAS EEPROM

2021-06-21 Thread Luben Tuikov
Debugfs RAS EEPROM files are available when
the ASIC supports RAS, and when the debugfs is
enabled, an also when "ras_enable" module
parameter is set to 0. However in this case,
we get a kernel oops when accessing some of
the "ras_..." controls in debugfs. The reason
for this is that struct amdgpu_ras::adev is
unset. This commit sets it, thus enabling access
to those facilities. Note that this facilitates
EEPROM access and not necessarily RAS features or
functionality.

Cc: Alexander Deucher 
Cc: John Clements 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index edf4c02d075f48..c6ae63893dbdb2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -1947,11 +1947,20 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
bool exc_err_limit = false;
int ret;
 
-   if (adev->ras_enabled && con)
-   data = >eh_data;
-   else
+   if (!con)
+   return 0;
+
+   /* Allow access to RAS EEPROM via debugfs, when the ASIC
+* supports RAS and debugfs is enabled, but when
+* adev->ras_enabled is unset, i.e. when "ras_enable"
+* module parameter is set to 0.
+*/
+   con->adev = adev;
+
+   if (!adev->ras_enabled)
return 0;
 
+   data = >eh_data;
*data = kmalloc(sizeof(**data), GFP_KERNEL | __GFP_ZERO);
if (!*data) {
ret = -ENOMEM;
@@ -1961,7 +1970,6 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
mutex_init(>recovery_lock);
INIT_WORK(>recovery_work, amdgpu_ras_do_recovery);
atomic_set(>in_recovery, 0);
-   con->adev = adev;
 
max_eeprom_records_count = amdgpu_ras_eeprom_max_record_count();
amdgpu_ras_validate_threshold(adev, max_eeprom_records_count);
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 31/43] drm/amdgpu: Fix width of I2C address

2021-06-21 Thread Luben Tuikov
The I2C address is kept as a 16-bit quantity in
the kernel. The I2C_TAR::I2C_TAR field is 10-bit
wide.

Fix the width of the I2C address for Vega20 from 8
bits to 16 bits to accommodate the full spectrum
of I2C address space.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 19 +++
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c 
b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index e403ba556e5590..65035256756679 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -111,12 +111,15 @@ static void smu_v11_0_i2c_set_clock(struct i2c_adapter 
*control)
WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_SDA_HOLD, 20);
 }
 
-static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, uint8_t 
address)
+static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, u16 address)
 {
struct amdgpu_device *adev = to_amdgpu_device(control);
 
-   /* We take 7-bit addresses raw */
-   WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TAR, (address & 0xFF));
+   /* The IC_TAR::IC_TAR field is 10-bits wide.
+* It takes a 7-bit or 10-bit addresses as an address,
+* i.e. no read/write bit--no wire format, just the address.
+*/
+   WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TAR, address & 0x3FF);
 }
 
 static uint32_t smu_v11_0_i2c_poll_tx_status(struct i2c_adapter *control)
@@ -215,8 +218,8 @@ static uint32_t smu_v11_0_i2c_poll_rx_status(struct 
i2c_adapter *control)
  * Returns 0 on success or error.
  */
 static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control,
- uint8_t address, uint8_t *data,
- uint32_t numbytes, uint32_t i2c_flag)
+  u16 address, u8 *data,
+  u32 numbytes, u32 i2c_flag)
 {
struct amdgpu_device *adev = to_amdgpu_device(control);
uint32_t bytes_sent, reg, ret = 0;
@@ -225,7 +228,7 @@ static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter 
*control,
bytes_sent = 0;
 
DRM_DEBUG_DRIVER("I2C_Transmit(), address = %x, bytes = %d , data: ",
-(uint16_t)address, numbytes);
+address, numbytes);
 
if (drm_debug_enabled(DRM_UT_DRIVER)) {
print_hex_dump(KERN_INFO, "data: ", DUMP_PREFIX_NONE,
@@ -318,8 +321,8 @@ static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter 
*control,
  * Returns 0 on success or error.
  */
 static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control,
-uint8_t address, uint8_t *data,
-uint32_t numbytes, uint8_t i2c_flag)
+ u16 address, u8 *data,
+ u32 numbytes, u32 i2c_flag)
 {
struct amdgpu_device *adev = to_amdgpu_device(control);
uint32_t bytes_received, ret = I2C_OK;
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 33/43] drm/amdgpu: Fix amdgpu_ras_eeprom_init()

2021-06-21 Thread Luben Tuikov
No need to account for the 2 bytes of EEPROM
address--this is now well abstracted away by
the fixes the the lower layers.

Cc: Andrey Grodzovsky 
Cc: Alexander Deucher 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index dc48c556398039..7d0f9e1e62dc4f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -306,7 +306,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control 
*control,
return ret;
}
 
-   __decode_table_header_from_buff(hdr, [2]);
+   __decode_table_header_from_buff(hdr, buff);
 
if (hdr->header == RAS_TABLE_HDR_VAL) {
control->num_recs = (hdr->tbl_size - RAS_TABLE_HEADER_SIZE) /
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 09/43] drm/amdgpu: add I2C_CLASS_HWMON to SMU i2c buses

2021-06-21 Thread Luben Tuikov
From: Alex Deucher 

Not sure that this really matters that much, but these could
have various other hwmon chips on them.

Signed-off-by: Alex Deucher 
Reviewed-by: Luben Tuikov 
---
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c  | 2 +-
 drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c   | 2 +-
 drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 2 +-
 drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c 
b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index 1d8f6d5180e099..3a164d93c90293 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -665,7 +665,7 @@ int smu_v11_0_i2c_control_init(struct i2c_adapter *control)
 
mutex_init(>pm.smu_i2c_mutex);
control->owner = THIS_MODULE;
-   control->class = I2C_CLASS_SPD;
+   control->class = I2C_CLASS_SPD | I2C_CLASS_HWMON;
control->dev.parent = >pdev->dev;
control->algo = _v11_0_i2c_algo;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index a6447822deb09f..404afc9979c69b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -2033,7 +2033,7 @@ static int arcturus_i2c_control_init(struct smu_context 
*smu, struct i2c_adapter
int res;
 
control->owner = THIS_MODULE;
-   control->class = I2C_CLASS_SPD;
+   control->class = I2C_CLASS_SPD | I2C_CLASS_HWMON;
control->dev.parent = >pdev->dev;
control->algo = _i2c_algo;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index e02db86ced6108..3303830afac7d0 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -2832,7 +2832,7 @@ static int navi10_i2c_control_init(struct smu_context 
*smu, struct i2c_adapter *
int res;
 
control->owner = THIS_MODULE;
-   control->class = I2C_CLASS_SPD;
+   control->class = I2C_CLASS_SPD | I2C_CLASS_HWMON;
control->dev.parent = >pdev->dev;
control->algo = _i2c_algo;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index b4aa489e4a431a..1d06641ad87890 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -3539,7 +3539,7 @@ static int sienna_cichlid_i2c_control_init(struct 
smu_context *smu, struct i2c_a
int res;
 
control->owner = THIS_MODULE;
-   control->class = I2C_CLASS_SPD;
+   control->class = I2C_CLASS_SPD | I2C_CLASS_HWMON;
control->dev.parent = >pdev->dev;
control->algo = _cichlid_i2c_algo;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 19/43] drm/amdgpu: Fixes to the AMDGPU EEPROM driver

2021-06-21 Thread Luben Tuikov
* When reading from the EEPROM device, there is no
  device limitation on the number of bytes
  read--they're simply sequenced out. Thus, read
  the whole data requested in one go.

* When writing to the EEPROM device, there is a
  256-byte page limit to write to before having to
  generate a STOP on the bus, as well as the
  address written to mustn't cross over the page
  boundary (it actually rolls over). Maximize the
  data written to per bus acquisition.

* Return the number of bytes read/written, or -errno.

* Add kernel doc.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c | 96 +++---
 1 file changed, 68 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
index d02ea083a6c69b..7fdb5bd2fc8bc8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
@@ -24,59 +24,99 @@
 #include "amdgpu_eeprom.h"
 #include "amdgpu.h"
 
-#define EEPROM_OFFSET_LENGTH 2
+/* AT24CM02 has a 256-byte write page size.
+ */
+#define EEPROM_PAGE_BITS   8
+#define EEPROM_PAGE_SIZE   (1U << EEPROM_PAGE_BITS)
+#define EEPROM_PAGE_MASK   (EEPROM_PAGE_SIZE - 1)
+
+#define EEPROM_OFFSET_SIZE 2
 
+/**
+ * amdgpu_eeprom_xfer -- Read/write from/to an I2C EEPROM device
+ * @i2c_adap: pointer to the I2C adapter to use
+ * @slave_addr: I2C address of the slave device
+ * @eeprom_addr: EEPROM address from which to read/write
+ * @eeprom_buf: pointer to data buffer to read into/write from
+ * @buf_size: the size of @eeprom_buf
+ * @read: True if reading from the EEPROM, false if writing
+ *
+ * Returns the number of bytes read/written; -errno on error.
+ */
 int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
   u16 slave_addr, u16 eeprom_addr,
-  u8 *eeprom_buf, u16 bytes, bool read)
+  u8 *eeprom_buf, u16 buf_size, bool read)
 {
-   u8 eeprom_offset_buf[2];
-   u16 bytes_transferred;
+   u8 eeprom_offset_buf[EEPROM_OFFSET_SIZE];
struct i2c_msg msgs[] = {
{
.addr = slave_addr,
.flags = 0,
-   .len = EEPROM_OFFSET_LENGTH,
+   .len = EEPROM_OFFSET_SIZE,
.buf = eeprom_offset_buf,
},
{
.addr = slave_addr,
.flags = read ? I2C_M_RD : 0,
-   .len = bytes,
-   .buf = eeprom_buf,
},
};
+   const u8 *p = eeprom_buf;
int r;
+   u16 len;
+
+   r = 0;
+   for (len = 0; buf_size > 0;
+buf_size -= len, eeprom_addr += len, eeprom_buf += len) {
+   /* Set the EEPROM address we want to write to/read from.
+*/
+   msgs[0].buf[0] = (eeprom_addr >> 8) & 0xff;
+   msgs[0].buf[1] = eeprom_addr & 0xff;
 
-   msgs[0].buf[0] = ((eeprom_addr >> 8) & 0xff);
-   msgs[0].buf[1] = (eeprom_addr & 0xff);
+   if (!read) {
+   /* Write the maximum amount of data, without
+* crossing the device's page boundary, as per
+* its spec. Partial page writes are allowed,
+* starting at any location within the page,
+* so long as the page boundary isn't crossed
+* over (actually the page pointer rolls
+* over).
+*
+* As per the AT24CM02 EEPROM spec, after
+* writing into a page, the I2C driver MUST
+* terminate the transfer, i.e. in
+* "i2c_transfer()" below, with a STOP
+* condition, so that the self-timed write
+* cycle begins. This is implied for the
+* "i2c_transfer()" abstraction.
+*/
+   len = min(EEPROM_PAGE_SIZE - (eeprom_addr &
+ EEPROM_PAGE_MASK),
+ (u32)buf_size);
+   } else {
+   /* Reading from the EEPROM has no limitation
+* on the number of bytes read from the EEPROM
+* device--they are simply sequenced out.
+*/
+   len = buf_size;
+   }
+   msgs[1].len = len;
+   msgs[1].buf = eeprom_buf;
 
-   while (msgs[1].len) {
r = i2c_transfer(i2c_adap, msgs, ARRAY_SIZE(msgs));
-   if (r <= 0)
-   return r;
+   if (r 

[PATCH 15/43] drm/amdgpu: Send STOP for the last byte of msg only

2021-06-21 Thread Luben Tuikov
From: Andrey Grodzovsky 

Let's just ignore the I2C_M_STOP hint from upper
layer for SMU I2C code as there is no clean
mapping between single per I2C message STOP flag
at the kernel I2C layer and the SMU, per each byte
STOP flag. We will just by default set it at the
end of the SMU I2C message.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Andrey Grodzovsky 
Suggested-by: Lazar Lijo 
Signed-off-by: Luben Tuikov 
Reviewed-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c   | 4 ++--
 drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 4 ++--
 drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index a6d6ea1ef9e31b..fde03bb6ffe7c8 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1981,9 +1981,9 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
cmd->CmdConfig |= I2C_CMD_WRITE;
cmd->RegisterAddr = msg->buf[j];
}
-   if ((msg[i].flags & I2C_M_STOP) ||
-   (!remaining_bytes))
+   if (!remaining_bytes)
cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
+
if ((j == 0) && !(msg[i].flags & I2C_M_NOSTART))
cmd->CmdConfig |= CMDCONFIG_RESTART_BIT;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index e682bbd3c26d82..8bd3fa2ef7efea 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -2780,9 +2780,9 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
cmd->CmdConfig |= I2C_CMD_WRITE;
cmd->RegisterAddr = msg->buf[j];
}
-   if ((msg[i].flags & I2C_M_STOP) ||
-   (!remaining_bytes))
+   if (!remaining_bytes)
cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
+
if ((j == 0) && !(msg[i].flags & I2C_M_NOSTART))
cmd->CmdConfig |= CMDCONFIG_RESTART_BIT;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 93acf3f869227a..7c266420e31cc7 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -3487,9 +3487,9 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter 
*i2c_adap,
cmd->CmdConfig |= CMDCONFIG_READWRITE_MASK;
cmd->ReadWriteData = msg->buf[j];
}
-   if ((msg[i].flags & I2C_M_STOP) ||
-   (!remaining_bytes))
+   if (!remaining_bytes)
cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
+
if ((j == 0) && !(msg[i].flags & I2C_M_NOSTART))
cmd->CmdConfig |= CMDCONFIG_RESTART_BIT;
}
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 24/43] drm/amdgpu: I2C class is HWMON

2021-06-21 Thread Luben Tuikov
Set the auto-discoverable class of I2C bus to
HWMON. Remove SPD.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Reviewed-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c  | 2 +-
 drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c   | 2 +-
 drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 2 +-
 drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c 
b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index b8d6d308fb06a0..e403ba556e5590 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -667,7 +667,7 @@ int smu_v11_0_i2c_control_init(struct i2c_adapter *control)
 
mutex_init(>pm.smu_i2c_mutex);
control->owner = THIS_MODULE;
-   control->class = I2C_CLASS_SPD | I2C_CLASS_HWMON;
+   control->class = I2C_CLASS_HWMON;
control->dev.parent = >pdev->dev;
control->algo = _v11_0_i2c_algo;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 33210119a28ec1..9fccdd2d3e73ec 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -2046,7 +2046,7 @@ static int arcturus_i2c_control_init(struct smu_context 
*smu, struct i2c_adapter
int res;
 
control->owner = THIS_MODULE;
-   control->class = I2C_CLASS_SPD | I2C_CLASS_HWMON;
+   control->class = I2C_CLASS_HWMON;
control->dev.parent = >pdev->dev;
control->algo = _i2c_algo;
control->quirks = _i2c_control_quirks;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index c9519a1a5ca633..5cecb4be57c554 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -2844,7 +2844,7 @@ static int navi10_i2c_control_init(struct smu_context 
*smu, struct i2c_adapter *
int res;
 
control->owner = THIS_MODULE;
-   control->class = I2C_CLASS_SPD | I2C_CLASS_HWMON;
+   control->class = I2C_CLASS_HWMON;
control->dev.parent = >pdev->dev;
control->algo = _i2c_algo;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 9a14103cf9729f..2444e13c4901b3 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -3551,7 +3551,7 @@ static int sienna_cichlid_i2c_control_init(struct 
smu_context *smu, struct i2c_a
int res;
 
control->owner = THIS_MODULE;
-   control->class = I2C_CLASS_SPD | I2C_CLASS_HWMON;
+   control->class = I2C_CLASS_HWMON;
control->dev.parent = >pdev->dev;
control->algo = _cichlid_i2c_algo;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 08/43] drm/amdgpu: i2c subsystem uses 7 bit addresses

2021-06-21 Thread Luben Tuikov
From: Alex Deucher 

Convert from 8 bit to 7 bit.

Signed-off-by: Alex Deucher 
Reviewed-by: Luben Tuikov 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 10 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
index 224da573ba1b59..2b854bc6ae34bb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
@@ -29,7 +29,7 @@
 #include "amdgpu_fru_eeprom.h"
 #include "amdgpu_eeprom.h"
 
-#define I2C_PRODUCT_INFO_ADDR  0xAC
+#define I2C_PRODUCT_INFO_ADDR  0x56
 #define I2C_PRODUCT_INFO_OFFSET0xC0
 
 static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index e22a0b45f70108..2b981e96ce5b9e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -28,11 +28,11 @@
 #include "atom.h"
 #include "amdgpu_eeprom.h"
 
-#define EEPROM_I2C_TARGET_ADDR_VEGA20  0xA0
-#define EEPROM_I2C_TARGET_ADDR_ARCTURUS0xA8
-#define EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342   0xA0
-#define EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID   0xA0
-#define EEPROM_I2C_TARGET_ADDR_ALDEBARAN0xA0
+#define EEPROM_I2C_TARGET_ADDR_VEGA20  0x50
+#define EEPROM_I2C_TARGET_ADDR_ARCTURUS0x54
+#define EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342   0x50
+#define EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID   0x50
+#define EEPROM_I2C_TARGET_ADDR_ALDEBARAN0x50  
 
 /*
  * The 2 macros bellow represent the actual size in bytes that
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 13/43] dmr/amdgpu: Add RESTART handling also to smu_v11_0_i2c (VG20)

2021-06-21 Thread Luben Tuikov
From: Andrey Grodzovsky 

Also generilize the code to accept and translate to
HW bits any I2C relvent flags both for read and write.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Andrey Grodzovsky 
Signed-off-by: Luben Tuikov 
Reviewed-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 22 --
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c 
b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index 3193d566f4f87e..5a90d9351b22eb 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -530,13 +530,11 @@ static bool smu_v11_0_i2c_bus_unlock(struct i2c_adapter 
*control)
 /* I2C GLUE /
 
 static uint32_t smu_v11_0_i2c_read_data(struct i2c_adapter *control,
-   struct i2c_msg *msg)
+   struct i2c_msg *msg, uint32_t i2c_flag)
 {
-   uint32_t  ret = 0;
+   uint32_t  ret;
 
-   /* Now read data starting with that address */
-   ret = smu_v11_0_i2c_receive(control, msg->addr, msg->buf, msg->len,
-   I2C_RESTART);
+   ret = smu_v11_0_i2c_receive(control, msg->addr, msg->buf, msg->len, 
i2c_flag);
 
if (ret != I2C_OK)
DRM_ERROR("ReadData() - I2C error occurred :%x", ret);
@@ -545,12 +543,11 @@ static uint32_t smu_v11_0_i2c_read_data(struct 
i2c_adapter *control,
 }
 
 static uint32_t smu_v11_0_i2c_write_data(struct i2c_adapter *control,
-   struct i2c_msg *msg)
+   struct i2c_msg *msg, uint32_t i2c_flag)
 {
uint32_t  ret;
 
-   /* Send I2C_NO_STOP unless requested to stop. */
-   ret = smu_v11_0_i2c_transmit(control, msg->addr, msg->buf, msg->len, 
((msg->flags & I2C_M_STOP) ? 0 : I2C_NO_STOP));
+   ret = smu_v11_0_i2c_transmit(control, msg->addr, msg->buf, msg->len, 
i2c_flag);
 
if (ret != I2C_OK)
DRM_ERROR("WriteI2CData() - I2C error occurred :%x", ret);
@@ -601,12 +598,17 @@ static int smu_v11_0_i2c_xfer(struct i2c_adapter 
*i2c_adap,
smu_v11_0_i2c_init(i2c_adap);
 
for (i = 0; i < num; i++) {
+   uint32_t i2c_flag = ((msgs[i].flags & I2C_M_NOSTART) ? 0 : 
I2C_RESTART) ||
+   (((msgs[i].flags & I2C_M_STOP) ? 0 : 
I2C_NO_STOP));
+
if (msgs[i].flags & I2C_M_RD)
ret = smu_v11_0_i2c_read_data(i2c_adap,
- msgs + i);
+ msgs + i,
+ i2c_flag);
else
ret = smu_v11_0_i2c_write_data(i2c_adap,
-  msgs + i);
+  msgs + i,
+  i2c_flag);
 
if (ret != I2C_OK) {
num = -EIO;
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 06/43] drm/amdgpu/ras: switch ras eeprom handling to use generic helper

2021-06-21 Thread Luben Tuikov
From: Alex Deucher 

Use the new helper rather than doing i2c transfers directly.

Signed-off-by: Alex Deucher 
Reviewed-by: Luben Tuikov 
---
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c| 86 ++-
 1 file changed, 28 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index f40c871da0c623..e22a0b45f70108 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -26,6 +26,7 @@
 #include "amdgpu_ras.h"
 #include 
 #include "atom.h"
+#include "amdgpu_eeprom.h"
 
 #define EEPROM_I2C_TARGET_ADDR_VEGA20  0xA0
 #define EEPROM_I2C_TARGET_ADDR_ARCTURUS0xA8
@@ -148,22 +149,13 @@ static int __update_table_header(struct 
amdgpu_ras_eeprom_control *control,
 {
int ret = 0;
struct amdgpu_device *adev = to_amdgpu_device(control);
-   struct i2c_msg msg = {
-   .addr   = 0,
-   .flags  = 0,
-   .len= EEPROM_ADDRESS_SIZE + 
EEPROM_TABLE_HEADER_SIZE,
-   .buf= buff,
-   };
 
-
-   *(uint16_t *)buff = EEPROM_HDR_START;
-   __encode_table_header_to_buff(>tbl_hdr, buff + 
EEPROM_ADDRESS_SIZE);
-
-   msg.addr = control->i2c_address;
+   __encode_table_header_to_buff(>tbl_hdr, buff);
 
/* i2c may be unstable in gpu reset */
down_read(>reset_sem);
-   ret = i2c_transfer(>pm.smu_i2c, , 1);
+   ret = amdgpu_eeprom_xfer(>pm.smu_i2c, control->i2c_address,
+EEPROM_HDR_START, buff, 
EEPROM_TABLE_HEADER_SIZE, false);
up_read(>reset_sem);
 
if (ret < 1)
@@ -289,15 +281,9 @@ int amdgpu_ras_eeprom_init(struct 
amdgpu_ras_eeprom_control *control,
 {
int ret = 0;
struct amdgpu_device *adev = to_amdgpu_device(control);
-   unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 
0 };
+   unsigned char buff[EEPROM_TABLE_HEADER_SIZE] = { 0 };
struct amdgpu_ras_eeprom_table_header *hdr = >tbl_hdr;
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
-   struct i2c_msg msg = {
-   .addr   = 0,
-   .flags  = I2C_M_RD,
-   .len= EEPROM_ADDRESS_SIZE + 
EEPROM_TABLE_HEADER_SIZE,
-   .buf= buff,
-   };
 
*exceed_err_limit = false;
 
@@ -313,9 +299,9 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control 
*control,
 
mutex_init(>tbl_mutex);
 
-   msg.addr = control->i2c_address;
/* Read/Create table header from EEPROM address 0 */
-   ret = i2c_transfer(>pm.smu_i2c, , 1);
+   ret = amdgpu_eeprom_xfer(>pm.smu_i2c, control->i2c_address,
+EEPROM_HDR_START, buff, 
EEPROM_TABLE_HEADER_SIZE, true);
if (ret < 1) {
DRM_ERROR("Failed to read EEPROM table header, ret:%d", ret);
return ret;
@@ -442,6 +428,7 @@ static uint32_t __correct_eeprom_dest_address(uint32_t 
curr_address)
 
 bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev)
 {
+
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
 
if (!__is_ras_eeprom_supported(adev))
@@ -470,11 +457,11 @@ int amdgpu_ras_eeprom_process_recods(struct 
amdgpu_ras_eeprom_control *control,
int num)
 {
int i, ret = 0;
-   struct i2c_msg *msgs, *msg;
unsigned char *buffs, *buff;
struct eeprom_table_record *record;
struct amdgpu_device *adev = to_amdgpu_device(control);
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
+   u16 slave_addr;
 
if (!__is_ras_eeprom_supported(adev))
return 0;
@@ -486,12 +473,6 @@ int amdgpu_ras_eeprom_process_recods(struct 
amdgpu_ras_eeprom_control *control,
 
mutex_lock(>tbl_mutex);
 
-   msgs = kcalloc(num, sizeof(*msgs), GFP_KERNEL);
-   if (!msgs) {
-   ret = -ENOMEM;
-   goto free_buff;
-   }
-
/*
 * If saved bad pages number exceeds the bad page threshold for
 * the whole VRAM, update table header to mark the BAD GPU tag
@@ -521,9 +502,8 @@ int amdgpu_ras_eeprom_process_recods(struct 
amdgpu_ras_eeprom_control *control,
 * 256b
 */
for (i = 0; i < num; i++) {
-   buff = [i * (EEPROM_ADDRESS_SIZE + 
EEPROM_TABLE_RECORD_SIZE)];
+   buff = [i * EEPROM_TABLE_RECORD_SIZE];
record = [i];
-   msg = [i];
 
control->next_addr = 
__correct_eeprom_dest_address(control->next_addr);
 
@@ -531,20 +511,26 @@ int amdgpu_ras_eeprom_process_recods(struct 
amdgpu_ras_eeprom_control *control,
 * Update bits 16,17 of EEPROM address in I2C address by 
setting them
 * to bits 1,2 of Device address byte
 */

[PATCH 18/43] drm/amdgpu: Fix Vega20 I2C to be agnostic (v2)

2021-06-21 Thread Luben Tuikov
Teach Vega20 I2C to be agnostic. Allow addressing
different devices while the master holds the bus.
Set STOP as per the controller's specification.

v2: Qualify generating ReSTART before the 1st byte
of the message, when set by the caller, as
those functions are separated, as caught by
Andrey G.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c |   4 +-
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 105 +
 2 files changed, 69 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
index fe0e9b0c4d5a38..d02ea083a6c69b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
@@ -41,10 +41,10 @@ int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
},
{
.addr = slave_addr,
-   .flags = read ? I2C_M_RD: 0,
+   .flags = read ? I2C_M_RD : 0,
.len = bytes,
.buf = eeprom_buf,
-   }
+   },
};
int r;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c 
b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index 5a90d9351b22eb..b8d6d308fb06a0 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -41,9 +41,7 @@
 #define I2C_SW_TIMEOUT8
 #define I2C_ABORT 0x10
 
-/* I2C transaction flags */
-#define I2C_NO_STOP1
-#define I2C_RESTART2
+#define I2C_X_RESTART BIT(31)
 
 #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
 
@@ -205,9 +203,6 @@ static uint32_t smu_v11_0_i2c_poll_rx_status(struct 
i2c_adapter *control)
return ret;
 }
 
-
-
-
 /**
  * smu_v11_0_i2c_transmit - Send a block of data over the I2C bus to a slave 
device.
  *
@@ -252,21 +247,22 @@ static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter 
*control,
reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS);
if (REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)) {
do {
-   reg = 0;
-   /*
-* Prepare transaction, no need to set RESTART. 
I2C engine will send
-* START as soon as it sees data in TXFIFO
-*/
-   if (bytes_sent == 0)
-   reg = REG_SET_FIELD(reg, 
CKSVII2C_IC_DATA_CMD, RESTART,
-   (i2c_flag & 
I2C_RESTART) ? 1 : 0);
reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, 
DAT, data[bytes_sent]);
 
-   /* determine if we need to send STOP bit or not 
*/
-   if (numbytes == 1)
-   /* Final transaction, so send stop 
unless I2C_NO_STOP */
-   reg = REG_SET_FIELD(reg, 
CKSVII2C_IC_DATA_CMD, STOP,
-   (i2c_flag & 
I2C_NO_STOP) ? 0 : 1);
+   /* Final message, final byte, must
+* generate a STOP, to release the
+* bus, i.e. don't hold SCL low.
+*/
+   if (numbytes == 1 && i2c_flag & I2C_M_STOP)
+   reg = REG_SET_FIELD(reg,
+   
CKSVII2C_IC_DATA_CMD,
+   STOP, 1);
+
+   if (bytes_sent == 0 && i2c_flag & I2C_X_RESTART)
+   reg = REG_SET_FIELD(reg,
+   
CKSVII2C_IC_DATA_CMD,
+   RESTART, 1);
+
/* Write */
reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, 
CMD, 0);
WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, 
reg);
@@ -341,23 +337,21 @@ static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter 
*control,
 
smu_v11_0_i2c_clear_status(control);
 
-
/* Prepare transaction */
-
-   /* Each time we disable I2C, so this is not a restart */
-   if (bytes_received == 0)
-   reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART,
-   (i2c_flag & I2C_RESTART) ? 1 : 0);
-
reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, 0);
   

[PATCH 22/43] drm/amdgpu: RAS and FRU now use 19-bit I2C address

2021-06-21 Thread Luben Tuikov
Convert RAS and FRU code to use the 19-bit I2C
memory address and remove all "slave_addr", as
this is now absolved into the 19-bit address.

Cc: Jean Delvare 
Cc: John Clements 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 .../gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c| 19 ++---
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c| 82 +++
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h|  2 +-
 3 files changed, 39 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
index 2b854bc6ae34bb..69b9559f840ac3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
@@ -29,8 +29,8 @@
 #include "amdgpu_fru_eeprom.h"
 #include "amdgpu_eeprom.h"
 
-#define I2C_PRODUCT_INFO_ADDR  0x56
-#define I2C_PRODUCT_INFO_OFFSET0xC0
+#define FRU_EEPROM_MADDR0x6
+#define I2C_PRODUCT_INFO_OFFSET 0xC0
 
 static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
 {
@@ -62,12 +62,11 @@ static bool is_fru_eeprom_supported(struct amdgpu_device 
*adev)
 }
 
 static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
-  unsigned char *buff)
+ unsigned char *buff)
 {
int ret, size;
 
-   ret = amdgpu_eeprom_xfer(>pm.smu_i2c, I2C_PRODUCT_INFO_ADDR,
-addrptr, buff, 1, true);
+   ret = amdgpu_eeprom_xfer(>pm.smu_i2c, addrptr, buff, 1, true);
if (ret < 1) {
DRM_WARN("FRU: Failed to get size field");
return ret;
@@ -78,8 +77,8 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, 
uint32_t addrptr,
 */
size = buff[0] - I2C_PRODUCT_INFO_OFFSET;
 
-   ret = amdgpu_eeprom_xfer(>pm.smu_i2c, I2C_PRODUCT_INFO_ADDR,
-addrptr + 1, buff, size, true);
+   ret = amdgpu_eeprom_xfer(>pm.smu_i2c, addrptr + 1, buff, size,
+true);
if (ret < 1) {
DRM_WARN("FRU: Failed to get data field");
return ret;
@@ -91,8 +90,8 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, 
uint32_t addrptr,
 int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
 {
unsigned char buff[34];
-   int addrptr, size;
-   int len;
+   u32 addrptr;
+   int size, len;
 
if (!is_fru_eeprom_supported(adev))
return 0;
@@ -115,7 +114,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
 * Bytes 8-a are all 1-byte and refer to the size of the entire struct,
 * and the language field, so just start from 0xb, manufacturer size
 */
-   addrptr = 0xb;
+   addrptr = FRU_EEPROM_MADDR + 0xb;
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
if (size < 1) {
DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 2b981e96ce5b9e..f316fb11b16d9e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -28,11 +28,11 @@
 #include "atom.h"
 #include "amdgpu_eeprom.h"
 
-#define EEPROM_I2C_TARGET_ADDR_VEGA20  0x50
-#define EEPROM_I2C_TARGET_ADDR_ARCTURUS0x54
-#define EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342   0x50
-#define EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID   0x50
-#define EEPROM_I2C_TARGET_ADDR_ALDEBARAN0x50  
+#define EEPROM_I2C_MADDR_VEGA20 0x0
+#define EEPROM_I2C_MADDR_ARCTURUS   0x4
+#define EEPROM_I2C_MADDR_ARCTURUS_D342  0x0
+#define EEPROM_I2C_MADDR_SIENNA_CICHLID 0x0
+#define EEPROM_I2C_MADDR_ALDEBARAN  0x0
 
 /*
  * The 2 macros bellow represent the actual size in bytes that
@@ -58,7 +58,6 @@
 #define EEPROM_HDR_START 0
 #define EEPROM_RECORD_START (EEPROM_HDR_START + EEPROM_TABLE_HEADER_SIZE)
 #define EEPROM_MAX_RECORD_NUM ((EEPROM_SIZE_BYTES - EEPROM_TABLE_HEADER_SIZE) 
/ EEPROM_TABLE_RECORD_SIZE)
-#define EEPROM_ADDR_MSB_MASK GENMASK(17, 8)
 
 #define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, 
eeprom_control))->adev
 
@@ -74,43 +73,43 @@ static bool __is_ras_eeprom_supported(struct amdgpu_device 
*adev)
 }
 
 static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev,
-  uint16_t *i2c_addr)
+  struct amdgpu_ras_eeprom_control 
*control)
 {
struct atom_context *atom_ctx = adev->mode_info.atom_context;
 
-   if (!i2c_addr || !atom_ctx)
+   if (!control || !atom_ctx)
return false;
 
if (strnstr(atom_ctx->vbios_version,
"D342",

[PATCH 03/43] drm/amdgpu/pm: rework i2c xfers on arcturus (v4)

2021-06-21 Thread Luben Tuikov
From: Alex Deucher 

Make it generic so we can support more than just EEPROMs.

v2: fix restart handling between transactions.
v3: handle 7 to 8 bit addr conversion
v4: Fix  --> req. (Luben T)

Signed-off-by: Alex Deucher 
Signed-off-by: Luben Tuikov 
Reviewed-by: Luben Tuikov 
---
 .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 229 +-
 1 file changed, 58 insertions(+), 171 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 094df6f87cfc41..a6447822deb09f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1936,197 +1936,84 @@ static int arcturus_dpm_set_vcn_enable(struct 
smu_context *smu, bool enable)
return ret;
 }
 
-static void arcturus_fill_i2c_req(SwI2cRequest_t  *req, bool write,
- uint8_t address, uint32_t numbytes,
- uint8_t *data)
-{
-   int i;
-
-   req->I2CcontrollerPort = 0;
-   req->I2CSpeed = 2;
-   req->SlaveAddress = address;
-   req->NumCmds = numbytes;
-
-   for (i = 0; i < numbytes; i++) {
-   SwI2cCmd_t *cmd =  >SwI2cCmds[i];
-
-   /* First 2 bytes are always write for lower 2b EEPROM address */
-   if (i < 2)
-   cmd->Cmd = 1;
-   else
-   cmd->Cmd = write;
-
-
-   /* Add RESTART for read  after address filled */
-   cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 
0;
-
-   /* Add STOP in the end */
-   cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 
0;
-
-   /* Fill with data regardless if read or write to simplify code 
*/
-   cmd->RegisterAddr = data[i];
-   }
-}
-
-static int arcturus_i2c_read_data(struct i2c_adapter *control,
-  uint8_t address,
-  uint8_t *data,
-  uint32_t numbytes)
+static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
+struct i2c_msg *msgs, int num)
 {
-   uint32_t  i, ret = 0;
-   SwI2cRequest_t req;
-   struct amdgpu_device *adev = to_amdgpu_device(control);
+   struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
struct smu_table_context *smu_table = >smu.smu_table;
struct smu_table *table = _table->driver_table;
-
-   if (numbytes > MAX_SW_I2C_COMMANDS) {
-   dev_err(adev->dev, "numbytes requested %d is over max allowed 
%d\n",
-   numbytes, MAX_SW_I2C_COMMANDS);
-   return -EINVAL;
+   SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
+   u16 bytes_to_transfer, remaining_bytes, msg_bytes;
+   u16 available_bytes = MAX_SW_I2C_COMMANDS;
+   int i, j, r, c;
+   u8 slave;
+
+   /* only support a single slave addr per transaction */
+   slave = msgs[0].addr;
+   for (i = 0; i < num; i++) {
+   if (slave != msgs[i].addr)
+   return -EINVAL;
+   bytes_to_transfer += min(msgs[i].len, available_bytes);
+   available_bytes -= bytes_to_transfer;
}
 
-   memset(, 0, sizeof(req));
-   arcturus_fill_i2c_req(, false, address, numbytes, data);
-
-   mutex_lock(>smu.mutex);
-   /* Now read data starting with that address */
-   ret = smu_cmn_update_table(>smu, SMU_TABLE_I2C_COMMANDS, 0, ,
-   true);
-   mutex_unlock(>smu.mutex);
-
-   if (!ret) {
-   SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
-
-   /* Assume SMU  fills res.SwI2cCmds[i].Data with read bytes */
-   for (i = 0; i < numbytes; i++)
-   data[i] = res->SwI2cCmds[i].Data;
-
-   dev_dbg(adev->dev, "arcturus_i2c_read_data, address = %x, bytes 
= %d, data :",
- (uint16_t)address, numbytes);
+   req = kzalloc(sizeof(*req), GFP_KERNEL);
+   if (!req)
+   return -ENOMEM;
 
-   print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
-  8, 1, data, numbytes, false);
-   } else
-   dev_err(adev->dev, "arcturus_i2c_read_data - error occurred 
:%x", ret);
+   req->I2CcontrollerPort = 1;
+   req->I2CSpeed = I2C_SPEED_FAST_400K;
+   req->SlaveAddress = slave << 1; /* 8 bit addresses */
+   req->NumCmds = bytes_to_transfer;
 
-   return ret;
-}
+   remaining_bytes = bytes_to_transfer;
+   c = 0;
+   for (i = 0; i < num; i++) {
+   struct i2c_msg *msg = [i];
 
-static int arcturus_i2c_write_data(struct i2c_adapter *control,
-   uint8_t address,
-   

[PATCH 29/43] drm/amd/pm: Extend the I2C quirk table

2021-06-21 Thread Luben Tuikov
Extend the I2C quirk table for SMU access
controlled I2C adapters. Let the kernel I2C layer
check that the messages all have the same address,
and that their combined size doesn't exceed the
maximum size of a SMU software I2C request.

Suggested-by: Jean Delvare 
Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c   | 5 -
 drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 5 -
 drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 5 -
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 9fccdd2d3e73ec..3286c704bd08df 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -2036,8 +2036,11 @@ static const struct i2c_algorithm arcturus_i2c_algo = {
 
 
 static const struct i2c_adapter_quirks arcturus_i2c_control_quirks = {
-   .max_read_len = MAX_SW_I2C_COMMANDS,
+   .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR,
+   .max_read_len  = MAX_SW_I2C_COMMANDS,
.max_write_len = MAX_SW_I2C_COMMANDS,
+   .max_comb_1st_msg_len = 2,
+   .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
 };
 
 static int arcturus_i2c_control_init(struct smu_context *smu, struct 
i2c_adapter *control)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 5cecb4be57c554..9c171122384336 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -2834,8 +2834,11 @@ static const struct i2c_algorithm navi10_i2c_algo = {
 };
 
 static const struct i2c_adapter_quirks navi10_i2c_control_quirks = {
-   .max_read_len = MAX_SW_I2C_COMMANDS,
+   .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR,
+   .max_read_len  = MAX_SW_I2C_COMMANDS,
.max_write_len = MAX_SW_I2C_COMMANDS,
+   .max_comb_1st_msg_len = 2,
+   .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
 };
 
 static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter 
*control)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 2444e13c4901b3..37cfe0ccd6863b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -3541,8 +3541,11 @@ static const struct i2c_algorithm 
sienna_cichlid_i2c_algo = {
 };
 
 static const struct i2c_adapter_quirks sienna_cichlid_i2c_control_quirks = {
-   .max_read_len = MAX_SW_I2C_COMMANDS,
+   .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR,
+   .max_read_len  = MAX_SW_I2C_COMMANDS,
.max_write_len = MAX_SW_I2C_COMMANDS,
+   .max_comb_1st_msg_len = 2,
+   .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
 };
 
 static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct 
i2c_adapter *control)
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 02/43] drm/amdgpu/pm: rework i2c xfers on sienna cichlid (v4)

2021-06-21 Thread Luben Tuikov
From: Alex Deucher 

Make it generic so we can support more than just EEPROMs.

v2: fix restart handling between transactions.
v3: handle 7 to 8 bit addr conversion
v4: Fix  --> req. (Luben T)

Signed-off-by: Alex Deucher 
Signed-off-by: Luben Tuikov 
Reviewed-by: Luben Tuikov 
---
 .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c   | 229 +-
 1 file changed, 58 insertions(+), 171 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index c751f717a0daff..b4aa489e4a431a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -3442,197 +3442,84 @@ static void sienna_cichlid_dump_pptable(struct 
smu_context *smu)
dev_info(smu->adev->dev, "MmHubPadding[7] = 0x%x\n", 
pptable->MmHubPadding[7]);
 }
 
-static void sienna_cichlid_fill_i2c_req(SwI2cRequest_t  *req, bool write,
- uint8_t address, uint32_t numbytes,
- uint8_t *data)
-{
-   int i;
-
-   req->I2CcontrollerPort = 1;
-   req->I2CSpeed = 2;
-   req->SlaveAddress = address;
-   req->NumCmds = numbytes;
-
-   for (i = 0; i < numbytes; i++) {
-   SwI2cCmd_t *cmd =  >SwI2cCmds[i];
-
-   /* First 2 bytes are always write for lower 2b EEPROM address */
-   if (i < 2)
-   cmd->CmdConfig = CMDCONFIG_READWRITE_MASK;
-   else
-   cmd->CmdConfig = write ? CMDCONFIG_READWRITE_MASK : 0;
-
-
-   /* Add RESTART for read  after address filled */
-   cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 
0;
-
-   /* Add STOP in the end */
-   cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 
0;
-
-   /* Fill with data regardless if read or write to simplify code 
*/
-   cmd->ReadWriteData = data[i];
-   }
-}
-
-static int sienna_cichlid_i2c_read_data(struct i2c_adapter *control,
-  uint8_t address,
-  uint8_t *data,
-  uint32_t numbytes)
+static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
+  struct i2c_msg *msgs, int num)
 {
-   uint32_t  i, ret = 0;
-   SwI2cRequest_t req;
-   struct amdgpu_device *adev = to_amdgpu_device(control);
+   struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
struct smu_table_context *smu_table = >smu.smu_table;
struct smu_table *table = _table->driver_table;
-
-   if (numbytes > MAX_SW_I2C_COMMANDS) {
-   dev_err(adev->dev, "numbytes requested %d is over max allowed 
%d\n",
-   numbytes, MAX_SW_I2C_COMMANDS);
-   return -EINVAL;
+   SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
+   u16 bytes_to_transfer, remaining_bytes, msg_bytes;
+   u16 available_bytes = MAX_SW_I2C_COMMANDS;
+   int i, j, r, c;
+   u8 slave;
+
+   /* only support a single slave addr per transaction */
+   slave = msgs[0].addr;
+   for (i = 0; i < num; i++) {
+   if (slave != msgs[i].addr)
+   return -EINVAL;
+   bytes_to_transfer += min(msgs[i].len, available_bytes);
+   available_bytes -= bytes_to_transfer;
}
 
-   memset(, 0, sizeof(req));
-   sienna_cichlid_fill_i2c_req(, false, address, numbytes, data);
-
-   mutex_lock(>smu.mutex);
-   /* Now read data starting with that address */
-   ret = smu_cmn_update_table(>smu, SMU_TABLE_I2C_COMMANDS, 0, ,
-   true);
-   mutex_unlock(>smu.mutex);
-
-   if (!ret) {
-   SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
-
-   /* Assume SMU  fills res.SwI2cCmds[i].Data with read bytes */
-   for (i = 0; i < numbytes; i++)
-   data[i] = res->SwI2cCmds[i].ReadWriteData;
-
-   dev_dbg(adev->dev, "sienna_cichlid_i2c_read_data, address = %x, 
bytes = %d, data :",
- (uint16_t)address, numbytes);
+   req = kzalloc(sizeof(*req), GFP_KERNEL);
+   if (!req)
+   return -ENOMEM;
 
-   print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
-  8, 1, data, numbytes, false);
-   } else
-   dev_err(adev->dev, "sienna_cichlid_i2c_read_data - error 
occurred :%x", ret);
+   req->I2CcontrollerPort = 1;
+   req->I2CSpeed = I2C_SPEED_FAST_400K;
+   req->SlaveAddress = slave << 1; /* 8 bit addresses */
+   req->NumCmds = bytes_to_transfer;
 
-   return ret;
-}
+   remaining_bytes = bytes_to_transfer;
+   c = 0;
+   for (i = 0; i < num; i++) {
+   

[PATCH 00/43] I2C fixes (revision 2)

2021-06-21 Thread Luben Tuikov
I2C fixes from various people. Some RAS touch-ups too.

A rebased tree can also be found here: 
https://gitlab.freedesktop.org/ltuikov/linux/-/commits/i2c-rework-luben

Tested on Vega20 and Sienna Cichlid.

This first revision includes acks, squashes patch 33 by absolving it
into earlier commits it fixes, and includes a new patch, patch 40 to
deal with driver aborts seen on large writes to an I2C EEPROM device.

The second revision includes more Ack and R-B tags, and also includes
a break up of revision 1 patch number 36, into 4 patches, in order to
better show amdgpu_ras_eeprom.c rewrite.

Regards,
Luben

Aaron Rice (1):
  drm/amdgpu: rework smu11 i2c for generic operation

Alex Deucher (10):
  drm/amdgpu: add a mutex for the smu11 i2c bus (v2)
  drm/amdgpu/pm: rework i2c xfers on sienna cichlid (v4)
  drm/amdgpu/pm: rework i2c xfers on arcturus (v4)
  drm/amdgpu/pm: add smu i2c implementation for navi1x (v4)
  drm/amdgpu: add new helper for handling EEPROM i2c transfers
  drm/amdgpu/ras: switch ras eeprom handling to use generic helper
  drm/amdgpu/ras: switch fru eeprom handling to use generic helper (v2)
  drm/amdgpu: i2c subsystem uses 7 bit addresses
  drm/amdgpu: add I2C_CLASS_HWMON to SMU i2c buses
  drm/amdgpu: only set restart on first cmd of the smu i2c transaction

Andrey Grodzovsky (6):
  drm/amdgpu: Remember to wait 10ms for write buffer flush v2
  dmr/amdgpu: Add RESTART handling also to smu_v11_0_i2c (VG20)
  drm/amdgpu: Drop i > 0 restriction for issuing RESTART
  drm/amdgpu: Send STOP for the last byte of msg only
  drm/amd/pm: SMU I2C: Return number of messages processed
  drm/amdgpu/pm: ADD I2C quirk adapter table

Luben Tuikov (26):
  drm/amdgpu: Fix Vega20 I2C to be agnostic (v2)
  drm/amdgpu: Fixes to the AMDGPU EEPROM driver
  drm/amdgpu: EEPROM respects I2C quirks
  drm/amdgpu: I2C EEPROM full memory addressing
  drm/amdgpu: RAS and FRU now use 19-bit I2C address
  drm/amdgpu: Fix wrap-around bugs in RAS
  drm/amdgpu: I2C class is HWMON
  drm/amdgpu: RAS: EEPROM --> RAS
  drm/amdgpu: Rename misspelled function
  drm/amdgpu: RAS xfer to read/write
  drm/amdgpu: EEPROM: add explicit read and write
  drm/amd/pm: Extend the I2C quirk table
  drm/amd/pm: Simplify managed I2C transfer functions
  drm/amdgpu: Fix width of I2C address
  drm/amdgpu: Return result fix in RAS
  drm/amdgpu: Fix amdgpu_ras_eeprom_init()
  drm/amdgpu: Simplify RAS EEPROM checksum calculations
  drm/amdgpu: Use explicit cardinality for clarity
  drm/amdgpu: Nerf buff
  drm/amdgpu: Some renames
  drm/amdgpu: Get rid of test function
  drm/amdgpu: Optimize EEPROM RAS table I/O
  drm/amdgpu: RAS EEPROM table is now in debugfs
  drm/amdgpu: Fix koops when accessing RAS EEPROM
  drm/amdgpu: Use a single loop
  drm/amdgpu: Correctly disable the I2C IP block

 drivers/gpu/drm/amd/amdgpu/Makefile   |3 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c   |9 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c|  239 
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h|   37 +
 .../gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c|   32 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c   |  116 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h   |1 +
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c| 1253 +++--
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h|   70 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c   |2 +-
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c|  319 +++--
 drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h   |1 +
 .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c |  238 +---
 .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c   |  118 ++
 .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c   |  241 +---
 15 files changed, 1685 insertions(+), 994 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h

Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Guchun Chen 
Cc: Hawking Zhang 
Cc: Jean Delvare 
Cc: John Clements 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Xinhui Pan 

base-commit: 5d880fc07b8caaf734a066af61aef8d8c84da04c
-- 
2.32.0
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 12/43] drm/amdgpu: Remember to wait 10ms for write buffer flush v2

2021-06-21 Thread Luben Tuikov
From: Andrey Grodzovsky 

EEPROM spec requests this.

v2: Only to be done for write data transactions.

Signed-off-by: Andrey Grodzovsky 
Signed-off-by: Alex Deucher 
Reviewed-by: Luben Tuikov 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
index 10551660343278..fe0e9b0c4d5a38 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
@@ -55,6 +55,21 @@ int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
r = i2c_transfer(i2c_adap, msgs, ARRAY_SIZE(msgs));
if (r <= 0)
return r;
+
+   /* Only for write data */
+   if (!msgs[1].flags)
+   /*
+* According to EEPROM spec there is a MAX of 10 ms 
required for
+* EEPROM to flush internal RX buffer after STOP was 
issued at the
+* end of write transaction. During this time the 
EEPROM will not be
+* responsive to any more commands - so wait a bit more.
+*
+* TODO Improve to wait for first ACK for slave address 
after
+* internal write cycle done.
+*/
+   msleep(10);
+
+
bytes_transferred = r - EEPROM_OFFSET_LENGTH;
eeprom_addr += bytes_transferred;
msgs[0].buf[0] = ((eeprom_addr >> 8) & 0xff);
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 26/43] drm/amdgpu: Rename misspelled function

2021-06-21 Thread Luben Tuikov
Instead of fixing the spelling in
  amdgpu_ras_eeprom_process_recods(),
rename it to,
  amdgpu_ras_eeprom_xfer(),
to look similar to other I2C and protocol
transfer (read/write) functions.

Also to keep the column span to within reason by
using a shorter name.

Change the "num" function parameter from "int" to
"const u32" since it is the number of items
(records) to xfer, i.e. their count, which cannot
be a negative number.

Also swap the order of parameters, keeping the
pointer to records and their number next to each
other, while the direction now becomes the last
parameter.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c| 11 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 10 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h |  7 +++
 3 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 44a4363cace737..96a2f42d57bb2c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -1817,10 +1817,10 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device 
*adev)
save_count = data->count - control->num_recs;
/* only new entries are saved */
if (save_count > 0) {
-   if (amdgpu_ras_eeprom_process_recods(control,
-   
>bps[control->num_recs],
-   true,
-   save_count)) {
+   if (amdgpu_ras_eeprom_xfer(control,
+  >bps[control->num_recs],
+  save_count,
+  true)) {
dev_err(adev->dev, "Failed to save EEPROM table data!");
return -EIO;
}
@@ -1850,8 +1850,7 @@ static int amdgpu_ras_load_bad_pages(struct amdgpu_device 
*adev)
if (!bps)
return -ENOMEM;
 
-   if (amdgpu_ras_eeprom_process_recods(control, bps, false,
-   control->num_recs)) {
+   if (amdgpu_ras_eeprom_xfer(control, bps, control->num_recs, false)) {
dev_err(adev->dev, "Failed to load EEPROM table records!");
ret = -EIO;
goto out;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index d3678706bb736d..9e3fbc44b4bc4a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -432,9 +432,9 @@ bool amdgpu_ras_eeprom_check_err_threshold(struct 
amdgpu_device *adev)
return false;
 }
 
-int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
-struct eeprom_table_record *records,
-bool write, int num)
+int amdgpu_ras_eeprom_xfer(struct amdgpu_ras_eeprom_control *control,
+  struct eeprom_table_record *records,
+  const u32 num, bool write)
 {
int i, ret = 0;
unsigned char *buffs, *buff;
@@ -574,13 +574,13 @@ void amdgpu_ras_eeprom_test(struct 
amdgpu_ras_eeprom_control *control)
recs[i].retired_page = i;
}
 
-   if (!amdgpu_ras_eeprom_process_recods(control, recs, true, 1)) {
+   if (!amdgpu_ras_eeprom_xfer(control, recs, 1, true)) {
 
memset(recs, 0, sizeof(*recs) * 1);
 
control->next_addr = RAS_RECORD_START;
 
-   if (!amdgpu_ras_eeprom_process_recods(control, recs, false, 1)) 
{
+   if (!amdgpu_ras_eeprom_xfer(control, recs, 1, false)) {
for (i = 0; i < 1; i++)
DRM_INFO("rec.address :0x%llx, rec.retired_page 
:%llu",
 recs[i].address, recs[i].retired_page);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
index 4c4c3d840a35c5..6a1bd527bce57a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
@@ -82,10 +82,9 @@ int amdgpu_ras_eeprom_reset_table(struct 
amdgpu_ras_eeprom_control *control);
 
 bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev);
 
-int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
-   struct eeprom_table_record *records,
-   bool write,
-   int num);
+int amdgpu_ras_eeprom_xfer(struct amdgpu_ras_eeprom_control *control,
+  struct eeprom_table_record *records,
+  

[PATCH 04/43] drm/amdgpu/pm: add smu i2c implementation for navi1x (v4)

2021-06-21 Thread Luben Tuikov
From: Alex Deucher 

And handle more than just EEPROMs.

v2: fix restart handling between transactions.
v3: handle 7 to 8 bit addr conversion
v4: Fix  --> req. (Luben T)

Signed-off-by: Alex Deucher 
Signed-off-by: Luben Tuikov 
Reviewed-by: Luben Tuikov 
---
 .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c   | 116 ++
 1 file changed, 116 insertions(+)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 1ba42b69ce7424..e02db86ced6108 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -2735,6 +2735,120 @@ static ssize_t navi10_get_legacy_gpu_metrics(struct 
smu_context *smu,
return sizeof(struct gpu_metrics_v1_3);
 }
 
+static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
+  struct i2c_msg *msgs, int num)
+{
+   struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
+   struct smu_table_context *smu_table = >smu.smu_table;
+   struct smu_table *table = _table->driver_table;
+   SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
+   u16 bytes_to_transfer, remaining_bytes, msg_bytes;
+   u16 available_bytes = MAX_SW_I2C_COMMANDS;
+   int i, j, r, c;
+   u8 slave;
+
+   /* only support a single slave addr per transaction */
+   slave = msgs[0].addr;
+   for (i = 0; i < num; i++) {
+   if (slave != msgs[i].addr)
+   return -EINVAL;
+   bytes_to_transfer += min(msgs[i].len, available_bytes);
+   available_bytes -= bytes_to_transfer;
+   }
+
+   req = kzalloc(sizeof(*req), GFP_KERNEL);
+   if (!req)
+   return -ENOMEM;
+
+   req->I2CcontrollerPort = 1;
+   req->I2CSpeed = I2C_SPEED_FAST_400K;
+   req->SlaveAddress = slave << 1; /* 8 bit addresses */
+   req->NumCmds = bytes_to_transfer;
+
+   remaining_bytes = bytes_to_transfer;
+   c = 0;
+   for (i = 0; i < num; i++) {
+   struct i2c_msg *msg = [i];
+
+   msg_bytes = min(msg->len, remaining_bytes);
+   for (j = 0; j < msg_bytes; j++) {
+   SwI2cCmd_t *cmd = >SwI2cCmds[c++];
+
+   remaining_bytes--;
+   if (!(msg[i].flags & I2C_M_RD)) {
+   /* write */
+   cmd->CmdConfig |= I2C_CMD_WRITE;
+   cmd->RegisterAddr = msg->buf[j];
+   }
+   if ((msg[i].flags & I2C_M_STOP) ||
+   (!remaining_bytes))
+   cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
+   if ((i > 0) && !(msg[i].flags & I2C_M_NOSTART))
+   cmd->CmdConfig |= CMDCONFIG_RESTART_BIT;
+   }
+   }
+   mutex_lock(>smu.mutex);
+   r = smu_cmn_update_table(>smu, SMU_TABLE_I2C_COMMANDS, 0, req, 
true);
+   mutex_unlock(>smu.mutex);
+   if (r)
+   goto fail;
+
+   remaining_bytes = bytes_to_transfer;
+   c = 0;
+   for (i = 0; i < num; i++) {
+   struct i2c_msg *msg = [i];
+
+   msg_bytes = min(msg->len, remaining_bytes);
+   for (j = 0; j < msg_bytes; j++) {
+   SwI2cCmd_t *cmd = >SwI2cCmds[c++];
+
+   remaining_bytes--;
+   if (msg[i].flags & I2C_M_RD)
+   msg->buf[j] = cmd->Data;
+   }
+   }
+   r = bytes_to_transfer;
+
+fail:
+   kfree(req);
+
+   return r;
+}
+
+static u32 navi10_i2c_func(struct i2c_adapter *adap)
+{
+   return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+
+static const struct i2c_algorithm navi10_i2c_algo = {
+   .master_xfer = navi10_i2c_xfer,
+   .functionality = navi10_i2c_func,
+};
+
+static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter 
*control)
+{
+   struct amdgpu_device *adev = to_amdgpu_device(control);
+   int res;
+
+   control->owner = THIS_MODULE;
+   control->class = I2C_CLASS_SPD;
+   control->dev.parent = >pdev->dev;
+   control->algo = _i2c_algo;
+   snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
+
+   res = i2c_add_adapter(control);
+   if (res)
+   DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
+
+   return res;
+}
+
+static void navi10_i2c_control_fini(struct smu_context *smu, struct 
i2c_adapter *control)
+{
+   i2c_del_adapter(control);
+}
+
 static ssize_t navi10_get_gpu_metrics(struct smu_context *smu,
  void **table)
 {
@@ -3078,6 +3192,8 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.set_default_dpm_table = navi10_set_default_dpm_table,
.dpm_set_vcn_enable = navi10_dpm_set_vcn_enable,
.dpm_set_jpeg_enable = 

[PATCH 14/43] drm/amdgpu: Drop i > 0 restriction for issuing RESTART

2021-06-21 Thread Luben Tuikov
From: Andrey Grodzovsky 

Drop i > 0 restriction for issuing RESTART.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Andrey Grodzovsky 
Signed-off-by: Luben Tuikov 
Reviewed-by: Luben Tuikov 
---
 drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c   | 2 +-
 drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 2 +-
 drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 843eb2357afaaf..a6d6ea1ef9e31b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1984,7 +1984,7 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
if ((msg[i].flags & I2C_M_STOP) ||
(!remaining_bytes))
cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
-   if ((i > 0) && (j == 0) && !(msg[i].flags & 
I2C_M_NOSTART))
+   if ((j == 0) && !(msg[i].flags & I2C_M_NOSTART))
cmd->CmdConfig |= CMDCONFIG_RESTART_BIT;
}
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index abb3647ea0a892..e682bbd3c26d82 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -2783,7 +2783,7 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
if ((msg[i].flags & I2C_M_STOP) ||
(!remaining_bytes))
cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
-   if ((i > 0) && (j == 0) && !(msg[i].flags & 
I2C_M_NOSTART))
+   if ((j == 0) && !(msg[i].flags & I2C_M_NOSTART))
cmd->CmdConfig |= CMDCONFIG_RESTART_BIT;
}
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 9e49505a6ac109..93acf3f869227a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -3490,7 +3490,7 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter 
*i2c_adap,
if ((msg[i].flags & I2C_M_STOP) ||
(!remaining_bytes))
cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
-   if ((i > 0) && (j == 0) && !(msg[i].flags & 
I2C_M_NOSTART))
+   if ((j == 0) && !(msg[i].flags & I2C_M_NOSTART))
cmd->CmdConfig |= CMDCONFIG_RESTART_BIT;
}
}
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 11/43] drm/amdgpu: only set restart on first cmd of the smu i2c transaction

2021-06-21 Thread Luben Tuikov
From: Alex Deucher 

Not sure how the firmware interprets these.

Signed-off-by: Alex Deucher 
Reviewed-by: Luben Tuikov 
---
 drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c   | 2 +-
 drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 2 +-
 drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 404afc9979c69b..843eb2357afaaf 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1984,7 +1984,7 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
if ((msg[i].flags & I2C_M_STOP) ||
(!remaining_bytes))
cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
-   if ((i > 0) && !(msg[i].flags & I2C_M_NOSTART))
+   if ((i > 0) && (j == 0) && !(msg[i].flags & 
I2C_M_NOSTART))
cmd->CmdConfig |= CMDCONFIG_RESTART_BIT;
}
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 3303830afac7d0..abb3647ea0a892 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -2783,7 +2783,7 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
if ((msg[i].flags & I2C_M_STOP) ||
(!remaining_bytes))
cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
-   if ((i > 0) && !(msg[i].flags & I2C_M_NOSTART))
+   if ((i > 0) && (j == 0) && !(msg[i].flags & 
I2C_M_NOSTART))
cmd->CmdConfig |= CMDCONFIG_RESTART_BIT;
}
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 1d06641ad87890..9e49505a6ac109 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -3490,7 +3490,7 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter 
*i2c_adap,
if ((msg[i].flags & I2C_M_STOP) ||
(!remaining_bytes))
cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
-   if ((i > 0) && !(msg[i].flags & I2C_M_NOSTART))
+   if ((i > 0) && (j == 0) && !(msg[i].flags & 
I2C_M_NOSTART))
cmd->CmdConfig |= CMDCONFIG_RESTART_BIT;
}
}
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 27/43] drm/amdgpu: RAS xfer to read/write

2021-06-21 Thread Luben Tuikov
Wrap amdgpu_ras_eeprom_xfer(..., bool write),
into amdgpu_ras_eeprom_read() and
amdgpu_ras_eeprom_write(), as that makes reading
and understanding the code clearer.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c   |  9 ---
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c| 24 +++
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h|  8 ---
 3 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 96a2f42d57bb2c..a9af6d0a2ed6bc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -1817,10 +1817,9 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev)
save_count = data->count - control->num_recs;
/* only new entries are saved */
if (save_count > 0) {
-   if (amdgpu_ras_eeprom_xfer(control,
-  >bps[control->num_recs],
-  save_count,
-  true)) {
+   if (amdgpu_ras_eeprom_write(control,
+   >bps[control->num_recs],
+   save_count)) {
dev_err(adev->dev, "Failed to save EEPROM table data!");
return -EIO;
}
@@ -1850,7 +1849,7 @@ static int amdgpu_ras_load_bad_pages(struct amdgpu_device 
*adev)
if (!bps)
return -ENOMEM;
 
-   if (amdgpu_ras_eeprom_xfer(control, bps, control->num_recs, false)) {
+   if (amdgpu_ras_eeprom_read(control, bps, control->num_recs)) {
dev_err(adev->dev, "Failed to load EEPROM table records!");
ret = -EIO;
goto out;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 9e3fbc44b4bc4a..550a31953d2da1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -432,9 +432,9 @@ bool amdgpu_ras_eeprom_check_err_threshold(struct 
amdgpu_device *adev)
return false;
 }
 
-int amdgpu_ras_eeprom_xfer(struct amdgpu_ras_eeprom_control *control,
-  struct eeprom_table_record *records,
-  const u32 num, bool write)
+static int amdgpu_ras_eeprom_xfer(struct amdgpu_ras_eeprom_control *control,
+ struct eeprom_table_record *records,
+ const u32 num, bool write)
 {
int i, ret = 0;
unsigned char *buffs, *buff;
@@ -554,6 +554,20 @@ int amdgpu_ras_eeprom_xfer(struct 
amdgpu_ras_eeprom_control *control,
return ret == num ? 0 : -EIO;
 }
 
+int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,
+  struct eeprom_table_record *records,
+  const u32 num)
+{
+   return amdgpu_ras_eeprom_xfer(control, records, num, false);
+}
+
+int amdgpu_ras_eeprom_write(struct amdgpu_ras_eeprom_control *control,
+   struct eeprom_table_record *records,
+   const u32 num)
+{
+   return amdgpu_ras_eeprom_xfer(control, records, num, true);
+}
+
 inline uint32_t amdgpu_ras_eeprom_get_record_max_length(void)
 {
return RAS_MAX_RECORD_NUM;
@@ -574,13 +588,13 @@ void amdgpu_ras_eeprom_test(struct 
amdgpu_ras_eeprom_control *control)
recs[i].retired_page = i;
}
 
-   if (!amdgpu_ras_eeprom_xfer(control, recs, 1, true)) {
+   if (!amdgpu_ras_eeprom_write(control, recs, 1)) {
 
memset(recs, 0, sizeof(*recs) * 1);
 
control->next_addr = RAS_RECORD_START;
 
-   if (!amdgpu_ras_eeprom_xfer(control, recs, 1, false)) {
+   if (!amdgpu_ras_eeprom_read(control, recs)) {
for (i = 0; i < 1; i++)
DRM_INFO("rec.address :0x%llx, rec.retired_page 
:%llu",
 recs[i].address, recs[i].retired_page);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
index 6a1bd527bce57a..fa9c509a8e2f2b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
@@ -82,9 +82,11 @@ int amdgpu_ras_eeprom_reset_table(struct 
amdgpu_ras_eeprom_control *control);
 
 bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev);
 
-int amdgpu_ras_eeprom_xfer(struct amdgpu_ras_eeprom_control *control,
-  struct eeprom_table_record *records,
-  const u32 num, bool write);
+int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control 

[PATCH 28/43] drm/amdgpu: EEPROM: add explicit read and write

2021-06-21 Thread Luben Tuikov
Add explicit amdgpu_eeprom_read() and
amdgpu_eeprom_write() for clarity.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h | 16 
 drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c |  5 ++---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 10 +-
 3 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h
index 417472be2712e6..966b434f0de2b7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h
@@ -29,4 +29,20 @@
 int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 eeprom_addr,
   u8 *eeprom_buf, u16 bytes, bool read);
 
+static inline int amdgpu_eeprom_read(struct i2c_adapter *i2c_adap,
+u32 eeprom_addr, u8 *eeprom_buf,
+u16 bytes)
+{
+   return amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, eeprom_buf, bytes,
+ true);
+}
+
+static inline int amdgpu_eeprom_write(struct i2c_adapter *i2c_adap,
+ u32 eeprom_addr, u8 *eeprom_buf,
+ u16 bytes)
+{
+   return amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, eeprom_buf, bytes,
+ false);
+}
+
 #endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
index 69b9559f840ac3..7709caeb233d67 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
@@ -66,7 +66,7 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, 
uint32_t addrptr,
 {
int ret, size;
 
-   ret = amdgpu_eeprom_xfer(>pm.smu_i2c, addrptr, buff, 1, true);
+   ret = amdgpu_eeprom_read(>pm.smu_i2c, addrptr, buff, 1);
if (ret < 1) {
DRM_WARN("FRU: Failed to get size field");
return ret;
@@ -77,8 +77,7 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, 
uint32_t addrptr,
 */
size = buff[0] - I2C_PRODUCT_INFO_OFFSET;
 
-   ret = amdgpu_eeprom_xfer(>pm.smu_i2c, addrptr + 1, buff, size,
-true);
+   ret = amdgpu_eeprom_read(>pm.smu_i2c, addrptr + 1, buff, size);
if (ret < 1) {
DRM_WARN("FRU: Failed to get data field");
return ret;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 550a31953d2da1..17cea35275e46c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -151,9 +151,9 @@ static int __update_table_header(struct 
amdgpu_ras_eeprom_control *control,
 
/* i2c may be unstable in gpu reset */
down_read(>reset_sem);
-   ret = amdgpu_eeprom_xfer(>pm.smu_i2c,
-control->i2c_address + RAS_HDR_START,
-buff, RAS_TABLE_HEADER_SIZE, false);
+   ret = amdgpu_eeprom_write(>pm.smu_i2c,
+ control->i2c_address + RAS_HDR_START,
+ buff, RAS_TABLE_HEADER_SIZE);
up_read(>reset_sem);
 
if (ret < 1)
@@ -298,9 +298,9 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control 
*control,
mutex_init(>tbl_mutex);
 
/* Read/Create table header from EEPROM address 0 */
-   ret = amdgpu_eeprom_xfer(>pm.smu_i2c,
+   ret = amdgpu_eeprom_read(>pm.smu_i2c,
 control->i2c_address + RAS_HDR_START,
-buff, RAS_TABLE_HEADER_SIZE, true);
+buff, RAS_TABLE_HEADER_SIZE);
if (ret < 1) {
DRM_ERROR("Failed to read EEPROM table header, ret:%d", ret);
return ret;
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 17/43] drm/amdgpu/pm: ADD I2C quirk adapter table

2021-06-21 Thread Luben Tuikov
From: Andrey Grodzovsky 

To be used by kernel clients of the adapter.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Andrey Grodzovsky 
Suggested-by: Lazar Lijo 
Signed-off-by: Luben Tuikov 
Reviewed-by: Luben Tuikov 
Reviewed-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c   | 7 +++
 drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 6 ++
 drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 6 ++
 3 files changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index c916ccc48bf67f..33210119a28ec1 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -2034,6 +2034,12 @@ static const struct i2c_algorithm arcturus_i2c_algo = {
.functionality = arcturus_i2c_func,
 };
 
+
+static const struct i2c_adapter_quirks arcturus_i2c_control_quirks = {
+   .max_read_len = MAX_SW_I2C_COMMANDS,
+   .max_write_len = MAX_SW_I2C_COMMANDS,
+};
+
 static int arcturus_i2c_control_init(struct smu_context *smu, struct 
i2c_adapter *control)
 {
struct amdgpu_device *adev = to_amdgpu_device(control);
@@ -2043,6 +2049,7 @@ static int arcturus_i2c_control_init(struct smu_context 
*smu, struct i2c_adapter
control->class = I2C_CLASS_SPD | I2C_CLASS_HWMON;
control->dev.parent = >pdev->dev;
control->algo = _i2c_algo;
+   control->quirks = _i2c_control_quirks;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
 
res = i2c_add_adapter(control);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 7018716b6c8585..c9519a1a5ca633 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -2833,6 +2833,11 @@ static const struct i2c_algorithm navi10_i2c_algo = {
.functionality = navi10_i2c_func,
 };
 
+static const struct i2c_adapter_quirks navi10_i2c_control_quirks = {
+   .max_read_len = MAX_SW_I2C_COMMANDS,
+   .max_write_len = MAX_SW_I2C_COMMANDS,
+};
+
 static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter 
*control)
 {
struct amdgpu_device *adev = to_amdgpu_device(control);
@@ -2843,6 +2848,7 @@ static int navi10_i2c_control_init(struct smu_context 
*smu, struct i2c_adapter *
control->dev.parent = >pdev->dev;
control->algo = _i2c_algo;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
+   control->quirks = _i2c_control_quirks;
 
res = i2c_add_adapter(control);
if (res)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 8f8e5c7df44a12..9a14103cf9729f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -3540,6 +3540,11 @@ static const struct i2c_algorithm 
sienna_cichlid_i2c_algo = {
.functionality = sienna_cichlid_i2c_func,
 };
 
+static const struct i2c_adapter_quirks sienna_cichlid_i2c_control_quirks = {
+   .max_read_len = MAX_SW_I2C_COMMANDS,
+   .max_write_len = MAX_SW_I2C_COMMANDS,
+};
+
 static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct 
i2c_adapter *control)
 {
struct amdgpu_device *adev = to_amdgpu_device(control);
@@ -3550,6 +3555,7 @@ static int sienna_cichlid_i2c_control_init(struct 
smu_context *smu, struct i2c_a
control->dev.parent = >pdev->dev;
control->algo = _cichlid_i2c_algo;
snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
+   control->quirks = _cichlid_i2c_control_quirks;
 
res = i2c_add_adapter(control);
if (res)
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 20/43] drm/amdgpu: EEPROM respects I2C quirks

2021-06-21 Thread Luben Tuikov
Consult the i2c_adapter.quirks table for
the maximum read/write data length per bus
transaction. Do not exceed this transaction
limit.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c | 80 +-
 1 file changed, 64 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
index 7fdb5bd2fc8bc8..94aeda1c7f8ca0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
@@ -32,20 +32,9 @@
 
 #define EEPROM_OFFSET_SIZE 2
 
-/**
- * amdgpu_eeprom_xfer -- Read/write from/to an I2C EEPROM device
- * @i2c_adap: pointer to the I2C adapter to use
- * @slave_addr: I2C address of the slave device
- * @eeprom_addr: EEPROM address from which to read/write
- * @eeprom_buf: pointer to data buffer to read into/write from
- * @buf_size: the size of @eeprom_buf
- * @read: True if reading from the EEPROM, false if writing
- *
- * Returns the number of bytes read/written; -errno on error.
- */
-int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
-  u16 slave_addr, u16 eeprom_addr,
-  u8 *eeprom_buf, u16 buf_size, bool read)
+static int __amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
+   u16 slave_addr, u16 eeprom_addr,
+   u8 *eeprom_buf, u16 buf_size, bool read)
 {
u8 eeprom_offset_buf[EEPROM_OFFSET_SIZE];
struct i2c_msg msgs[] = {
@@ -65,8 +54,8 @@ int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
u16 len;
 
r = 0;
-   for (len = 0; buf_size > 0;
-buf_size -= len, eeprom_addr += len, eeprom_buf += len) {
+   for ( ; buf_size > 0;
+ buf_size -= len, eeprom_addr += len, eeprom_buf += len) {
/* Set the EEPROM address we want to write to/read from.
 */
msgs[0].buf[0] = (eeprom_addr >> 8) & 0xff;
@@ -120,3 +109,62 @@ int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
 
return r < 0 ? r : eeprom_buf - p;
 }
+
+/**
+ * amdgpu_eeprom_xfer -- Read/write from/to an I2C EEPROM device
+ * @i2c_adap: pointer to the I2C adapter to use
+ * @slave_addr: I2C address of the slave device
+ * @eeprom_addr: EEPROM address from which to read/write
+ * @eeprom_buf: pointer to data buffer to read into/write from
+ * @buf_size: the size of @eeprom_buf
+ * @read: True if reading from the EEPROM, false if writing
+ *
+ * Returns the number of bytes read/written; -errno on error.
+ */
+int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
+  u16 slave_addr, u16 eeprom_addr,
+  u8 *eeprom_buf, u16 buf_size, bool read)
+{
+   const struct i2c_adapter_quirks *quirks = i2c_adap->quirks;
+   u16 limit;
+
+   if (!quirks)
+   limit = 0;
+   else if (read)
+   limit = quirks->max_read_len;
+   else
+   limit = quirks->max_write_len;
+
+   if (limit == 0) {
+   return __amdgpu_eeprom_xfer(i2c_adap, slave_addr, eeprom_addr,
+   eeprom_buf, buf_size, read);
+   } else if (limit <= EEPROM_OFFSET_SIZE) {
+   dev_err_ratelimited(_adap->dev,
+   "maddr:0x%04X size:0x%02X:quirk max_%s_len 
must be > %d",
+   eeprom_addr, buf_size,
+   read ? "read" : "write", 
EEPROM_OFFSET_SIZE);
+   return -EINVAL;
+   } else {
+   u16 ps; /* Partial size */
+   int res = 0, r;
+
+   /* The "limit" includes all data bytes sent/received,
+* which would include the EEPROM_OFFSET_SIZE bytes.
+* Account for them here.
+*/
+   limit -= EEPROM_OFFSET_SIZE;
+   for ( ; buf_size > 0;
+ buf_size -= ps, eeprom_addr += ps, eeprom_buf += ps) {
+   ps = min(limit, buf_size);
+
+   r = __amdgpu_eeprom_xfer(i2c_adap,
+slave_addr, eeprom_addr,
+eeprom_buf, ps, read);
+   if (r < 0)
+   return r;
+   res += r;
+   }
+
+   return res;
+   }
+}
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 16/43] drm/amd/pm: SMU I2C: Return number of messages processed

2021-06-21 Thread Luben Tuikov
From: Andrey Grodzovsky 

Fix from number of processed bytes to number of
processed I2C messages.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Andrey Grodzovsky 
Signed-off-by: Luben Tuikov 
Reviewed-by: Luben Tuikov 
Reviewed-by: Alexander Deucher 
---
 .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 43 +++
 .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c   | 43 +++
 .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c   | 43 +++
 3 files changed, 75 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index fde03bb6ffe7c8..c916ccc48bf67f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1943,9 +1943,8 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
struct smu_table_context *smu_table = >smu.smu_table;
struct smu_table *table = _table->driver_table;
SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
-   u16 bytes_to_transfer, remaining_bytes, msg_bytes;
-   u16 available_bytes = MAX_SW_I2C_COMMANDS;
-   int i, j, r, c;
+   short available_bytes = MAX_SW_I2C_COMMANDS;
+   int i, j, r, c, num_done = 0;
u8 slave;
 
/* only support a single slave addr per transaction */
@@ -1953,8 +1952,15 @@ static int arcturus_i2c_xfer(struct i2c_adapter 
*i2c_adap,
for (i = 0; i < num; i++) {
if (slave != msgs[i].addr)
return -EINVAL;
-   bytes_to_transfer += min(msgs[i].len, available_bytes);
-   available_bytes -= bytes_to_transfer;
+
+   available_bytes -= msgs[i].len;
+   if (available_bytes >= 0) {
+   num_done++;
+   } else {
+   /* This message and all the follwing won't be processed 
*/
+   available_bytes += msgs[i].len;
+   break;
+   }
}
 
req = kzalloc(sizeof(*req), GFP_KERNEL);
@@ -1964,24 +1970,28 @@ static int arcturus_i2c_xfer(struct i2c_adapter 
*i2c_adap,
req->I2CcontrollerPort = 1;
req->I2CSpeed = I2C_SPEED_FAST_400K;
req->SlaveAddress = slave << 1; /* 8 bit addresses */
-   req->NumCmds = bytes_to_transfer;
+   req->NumCmds = MAX_SW_I2C_COMMANDS - available_bytes;;
 
-   remaining_bytes = bytes_to_transfer;
c = 0;
-   for (i = 0; i < num; i++) {
+   for (i = 0; i < num_done; i++) {
struct i2c_msg *msg = [i];
 
-   msg_bytes = min(msg->len, remaining_bytes);
-   for (j = 0; j < msg_bytes; j++) {
+   for (j = 0; j < msg->len; j++) {
SwI2cCmd_t *cmd = >SwI2cCmds[c++];
 
-   remaining_bytes--;
if (!(msg[i].flags & I2C_M_RD)) {
/* write */
cmd->CmdConfig |= I2C_CMD_WRITE;
cmd->RegisterAddr = msg->buf[j];
}
-   if (!remaining_bytes)
+
+   /*
+* Insert STOP if we are at the last byte of either last
+* message for the transaction or the client explicitly
+* requires a STOP at this particular message.
+*/
+   if ((j == msg->len -1 ) &&
+   ((i == num_done - 1) || (msg[i].flags & 
I2C_M_STOP)))
cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
 
if ((j == 0) && !(msg[i].flags & I2C_M_NOSTART))
@@ -1994,21 +2004,18 @@ static int arcturus_i2c_xfer(struct i2c_adapter 
*i2c_adap,
if (r)
goto fail;
 
-   remaining_bytes = bytes_to_transfer;
c = 0;
-   for (i = 0; i < num; i++) {
+   for (i = 0; i < num_done; i++) {
struct i2c_msg *msg = [i];
 
-   msg_bytes = min(msg->len, remaining_bytes);
-   for (j = 0; j < msg_bytes; j++) {
+   for (j = 0; j < msg->len; j++) {
SwI2cCmd_t *cmd = >SwI2cCmds[c++];
 
-   remaining_bytes--;
if (msg[i].flags & I2C_M_RD)
msg->buf[j] = cmd->Data;
}
}
-   r = bytes_to_transfer;
+   r = num_done;
 
 fail:
kfree(req);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 8bd3fa2ef7efea..7018716b6c8585 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -2742,9 +2742,8 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
struct 

[PATCH 07/43] drm/amdgpu/ras: switch fru eeprom handling to use generic helper (v2)

2021-06-21 Thread Luben Tuikov
From: Alex Deucher 

Use the new helper rather than doing i2c transfers directly.

v2: fix typo

Signed-off-by: Alex Deucher 
Reviewed-by: Luben Tuikov 
---
 .../gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c| 22 +--
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
index 39b6c6bfab4533..224da573ba1b59 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
@@ -27,9 +27,9 @@
 #include "smu_v11_0_i2c.h"
 #include "atom.h"
 #include "amdgpu_fru_eeprom.h"
+#include "amdgpu_eeprom.h"
 
 #define I2C_PRODUCT_INFO_ADDR  0xAC
-#define I2C_PRODUCT_INFO_ADDR_SIZE 0x2
 #define I2C_PRODUCT_INFO_OFFSET0xC0
 
 static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
@@ -65,16 +65,9 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device 
*adev, uint32_t addrptr,
   unsigned char *buff)
 {
int ret, size;
-   struct i2c_msg msg = {
-   .addr   = I2C_PRODUCT_INFO_ADDR,
-   .flags  = I2C_M_RD,
-   .buf= buff,
-   };
-   buff[0] = 0;
-   buff[1] = addrptr;
-   msg.len = I2C_PRODUCT_INFO_ADDR_SIZE + 1;
-   ret = i2c_transfer(>pm.smu_i2c, , 1);
 
+   ret = amdgpu_eeprom_xfer(>pm.smu_i2c, I2C_PRODUCT_INFO_ADDR,
+addrptr, buff, 1, true);
if (ret < 1) {
DRM_WARN("FRU: Failed to get size field");
return ret;
@@ -83,13 +76,10 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device 
*adev, uint32_t addrptr,
/* The size returned by the i2c requires subtraction of 0xC0 since the
 * size apparently always reports as 0xC0+actual size.
 */
-   size = buff[2] - I2C_PRODUCT_INFO_OFFSET;
-   /* Add 1 since address field was 1 byte */
-   buff[1] = addrptr + 1;
-
-   msg.len = I2C_PRODUCT_INFO_ADDR_SIZE + size;
-   ret = i2c_transfer(>pm.smu_i2c, , 1);
+   size = buff[0] - I2C_PRODUCT_INFO_OFFSET;
 
+   ret = amdgpu_eeprom_xfer(>pm.smu_i2c, I2C_PRODUCT_INFO_ADDR,
+addrptr + 1, buff, size, true);
if (ret < 1) {
DRM_WARN("FRU: Failed to get data field");
return ret;
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 23/43] drm/amdgpu: Fix wrap-around bugs in RAS

2021-06-21 Thread Luben Tuikov
Fix the size of the EEPROM from 256000 bytes
to 262144 bytes (256 KiB).

Fix a couple or wrap around bugs. If a valid
value/address is 0 <= addr < size, the inverse of
this inequality (barring negative values which
make no sense here) is addr >= size. Fix this in
the RAS code.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c| 20 +--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index f316fb11b16d9e..3ef38b90fc3a83 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -52,12 +52,11 @@
 /* Bad GPU tag ‘BADG’ */
 #define EEPROM_TABLE_HDR_BAD 0x42414447
 
-/* Assume 2 Mbit size */
-#define EEPROM_SIZE_BYTES 256000
-#define EEPROM_PAGE__SIZE_BYTES 256
-#define EEPROM_HDR_START 0
-#define EEPROM_RECORD_START (EEPROM_HDR_START + EEPROM_TABLE_HEADER_SIZE)
-#define EEPROM_MAX_RECORD_NUM ((EEPROM_SIZE_BYTES - EEPROM_TABLE_HEADER_SIZE) 
/ EEPROM_TABLE_RECORD_SIZE)
+/* Assume 2-Mbit size */
+#define EEPROM_SIZE_BYTES   (256 * 1024)
+#define EEPROM_HDR_START0
+#define EEPROM_RECORD_START (EEPROM_HDR_START + EEPROM_TABLE_HEADER_SIZE)
+#define EEPROM_MAX_RECORD_NUM   ((EEPROM_SIZE_BYTES - 
EEPROM_TABLE_HEADER_SIZE) / EEPROM_TABLE_RECORD_SIZE)
 
 #define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, 
eeprom_control))->adev
 
@@ -402,9 +401,8 @@ static uint32_t __correct_eeprom_dest_address(uint32_t 
curr_address)
uint32_t next_address = curr_address + EEPROM_TABLE_RECORD_SIZE;
 
/* When all EEPROM memory used jump back to 0 address */
-   if (next_address > EEPROM_SIZE_BYTES) {
-   DRM_INFO("Reached end of EEPROM memory, jumping to 0 "
-"and overriding old record");
+   if (next_address >= EEPROM_SIZE_BYTES) {
+   DRM_INFO("Reached end of EEPROM memory, wrap around to 0.");
return EEPROM_RECORD_START;
}
 
@@ -476,7 +474,9 @@ int amdgpu_ras_eeprom_process_recods(struct 
amdgpu_ras_eeprom_control *control,
}
 
/* In case of overflow just start from beginning to not lose newest 
records */
-   if (write && (control->next_addr + EEPROM_TABLE_RECORD_SIZE * num > 
EEPROM_SIZE_BYTES))
+   if (write &&
+   (control->next_addr +
+EEPROM_TABLE_RECORD_SIZE * num >= EEPROM_SIZE_BYTES))
control->next_addr = EEPROM_RECORD_START;
 
/*
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 10/43] drm/amdgpu: rework smu11 i2c for generic operation

2021-06-21 Thread Luben Tuikov
From: Aaron Rice 

Handle things besides EEPROMS.

Signed-off-by: Aaron Rice 
Signed-off-by: Alex Deucher 
Reviewed-by: Luben Tuikov 
---
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 47 +-
 1 file changed, 9 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c 
b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index 3a164d93c90293..3193d566f4f87e 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -117,8 +117,7 @@ static void smu_v11_0_i2c_set_address(struct i2c_adapter 
*control, uint8_t addre
 {
struct amdgpu_device *adev = to_amdgpu_device(control);
 
-   /* Convert fromr 8-bit to 7-bit address */
-   address >>= 1;
+   /* We take 7-bit addresses raw */
WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TAR, (address & 0xFF));
 }
 
@@ -531,22 +530,14 @@ static bool smu_v11_0_i2c_bus_unlock(struct i2c_adapter 
*control)
 /* I2C GLUE /
 
 static uint32_t smu_v11_0_i2c_read_data(struct i2c_adapter *control,
-   uint8_t address,
-   uint8_t *data,
-   uint32_t numbytes)
+   struct i2c_msg *msg)
 {
uint32_t  ret = 0;
 
-   /* First 2 bytes are dummy write to set EEPROM address */
-   ret = smu_v11_0_i2c_transmit(control, address, data, 2, I2C_NO_STOP);
-   if (ret != I2C_OK)
-   goto Fail;
-
/* Now read data starting with that address */
-   ret = smu_v11_0_i2c_receive(control, address, data + 2, numbytes - 2,
+   ret = smu_v11_0_i2c_receive(control, msg->addr, msg->buf, msg->len,
I2C_RESTART);
 
-Fail:
if (ret != I2C_OK)
DRM_ERROR("ReadData() - I2C error occurred :%x", ret);
 
@@ -554,28 +545,16 @@ static uint32_t smu_v11_0_i2c_read_data(struct 
i2c_adapter *control,
 }
 
 static uint32_t smu_v11_0_i2c_write_data(struct i2c_adapter *control,
-uint8_t address,
-uint8_t *data,
-uint32_t numbytes)
+   struct i2c_msg *msg)
 {
uint32_t  ret;
 
-   ret = smu_v11_0_i2c_transmit(control, address, data, numbytes, 0);
+   /* Send I2C_NO_STOP unless requested to stop. */
+   ret = smu_v11_0_i2c_transmit(control, msg->addr, msg->buf, msg->len, 
((msg->flags & I2C_M_STOP) ? 0 : I2C_NO_STOP));
 
if (ret != I2C_OK)
DRM_ERROR("WriteI2CData() - I2C error occurred :%x", ret);
-   else
-   /*
-* According to EEPROM spec there is a MAX of 10 ms required for
-* EEPROM to flush internal RX buffer after STOP was issued at 
the
-* end of write transaction. During this time the EEPROM will 
not be
-* responsive to any more commands - so wait a bit more.
-*
-* TODO Improve to wait for first ACK for slave address after
-* internal write cycle done.
-*/
-   msleep(10);
-
+   
return ret;
 
 }
@@ -618,24 +597,16 @@ static int smu_v11_0_i2c_xfer(struct i2c_adapter 
*i2c_adap,
  struct i2c_msg *msgs, int num)
 {
int i, ret;
-   struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
-
-   if (!adev->pm.bus_locked) {
-   DRM_ERROR("I2C bus unlocked, stopping transaction!");
-   return -EIO;
-   }
 
smu_v11_0_i2c_init(i2c_adap);
 
for (i = 0; i < num; i++) {
if (msgs[i].flags & I2C_M_RD)
ret = smu_v11_0_i2c_read_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- msgs[i].buf, msgs[i].len);
+ msgs + i);
else
ret = smu_v11_0_i2c_write_data(i2c_adap,
-  (uint8_t)msgs[i].addr,
-  msgs[i].buf, 
msgs[i].len);
+  msgs + i);
 
if (ret != I2C_OK) {
num = -EIO;
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 21/43] drm/amdgpu: I2C EEPROM full memory addressing

2021-06-21 Thread Luben Tuikov
* "eeprom_addr" is now 32-bit wide.
* Remove "slave_addr" from the I2C EEPROM driver
  interface. The I2C EEPROM Device Type Identifier
  is fixed at 1010b, and the rest of the bits
  of the Device Address Byte/Device Select Code,
  are memory address bits, where the first three
  of those bits are the hardware selection bits.
  All this is now a 19-bit address and passed
  as "eeprom_addr". This abstracts the I2C bus
  for EEPROM devices for this I2C EEPROM driver.
  Now clients only pass the 19-bit EEPROM memory
  address, to the I2C EEPROM driver, as the 32-bit
  "eeprom_addr", from which they want to read from
  or write to.

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c | 88 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h |  4 +-
 2 files changed, 72 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
index 94aeda1c7f8ca0..a5a87affedabf1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
@@ -24,7 +24,7 @@
 #include "amdgpu_eeprom.h"
 #include "amdgpu.h"
 
-/* AT24CM02 has a 256-byte write page size.
+/* AT24CM02 and M24M02-R have a 256-byte write page size.
  */
 #define EEPROM_PAGE_BITS   8
 #define EEPROM_PAGE_SIZE   (1U << EEPROM_PAGE_BITS)
@@ -32,20 +32,72 @@
 
 #define EEPROM_OFFSET_SIZE 2
 
-static int __amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
-   u16 slave_addr, u16 eeprom_addr,
+/* EEPROM memory addresses are 19-bits long, which can
+ * be partitioned into 3, 8, 8 bits, for a total of 19.
+ * The upper 3 bits are sent as part of the 7-bit
+ * "Device Type Identifier"--an I2C concept, which for EEPROM devices
+ * is hard-coded as 1010b, indicating that it is an EEPROM
+ * device--this is the wire format, followed by the upper
+ * 3 bits of the 19-bit address, followed by the direction,
+ * followed by two bytes holding the rest of the 16-bits of
+ * the EEPROM memory address. The format on the wire for EEPROM
+ * devices is: 1010XYZD, A15:A8, A7:A0,
+ * Where D is the direction and sequenced out by the hardware.
+ * Bits XYZ are memory address bits 18, 17 and 16.
+ * These bits are compared to how pins 1-3 of the part are connected,
+ * depending on the size of the part, more on that later.
+ *
+ * Note that of this wire format, a client is in control
+ * of, and needs to specify only XYZ, A15:A8, A7:0, bits,
+ * which is exactly the EEPROM memory address, or offset,
+ * in order to address up to 8 EEPROM devices on the I2C bus.
+ *
+ * For instance, a 2-Mbit I2C EEPROM part, addresses all its bytes,
+ * using an 18-bit address, bit 17 to 0 and thus would use all but one bit of
+ * the 19 bits previously mentioned. The designer would then not connect
+ * pins 1 and 2, and pin 3 usually named "A_2" or "E2", would be connected to
+ * either Vcc or GND. This would allow for up to two 2-Mbit parts on
+ * the same bus, where one would be addressable with bit 18 as 1, and
+ * the other with bit 18 of the address as 0.
+ *
+ * For a 2-Mbit part, bit 18 is usually known as the "Chip Enable" or
+ * "Hardware Address Bit". This bit is compared to the load on pin 3
+ * of the device, described above, and if there is a match, then this
+ * device responds to the command. This way, you can connect two
+ * 2-Mbit EEPROM devices on the same bus, but see one contiguous
+ * memory from 0 to 7h, where address 0 to 3 is in the device
+ * whose pin 3 is connected to GND, and address 4 to 7h is in
+ * the 2nd device, whose pin 3 is connected to Vcc.
+ *
+ * This addressing you encode in the 32-bit "eeprom_addr" below,
+ * namely the 19-bits "XYZ,A15:A0", as a single 19-bit address. For
+ * instance, eeprom_addr = 0x6DA01, is 110_1101_1010__0001, where
+ * XYZ=110b, and A15:A0=DA01h. The XYZ bits become part of the device
+ * address, and the rest of the address bits are sent as the memory
+ * address bytes.
+ *
+ * That is, for an I2C EEPROM driver everything is controlled by
+ * the "eeprom_addr".
+ *
+ * P.S. If you need to write, lock and read the Identification Page,
+ * (M24M02-DR device only, which we do not use), change the "7" to
+ * "0xF" in the macro below, and let the client set bit 20 to 1 in
+ * "eeprom_addr", and set A10 to 0 to write into it, and A10 and A1 to
+ * 1 to lock it permanently.
+ */
+#define MAKE_I2C_ADDR(_aa) ((0xA << 3) | (((_aa) >> 16) & 7))
+
+static int __amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 eeprom_addr,
u8 *eeprom_buf, u16 buf_size, bool read)
 {
u8 eeprom_offset_buf[EEPROM_OFFSET_SIZE];
struct i2c_msg msgs[] = {
{
-   .addr = slave_addr,
.flags = 0,
.len 

[PATCH 05/43] drm/amdgpu: add new helper for handling EEPROM i2c transfers

2021-06-21 Thread Luben Tuikov
From: Alex Deucher 

Encapsulates the i2c protocol handling so other parts of the
driver can just tell it the offset and size of data to write.

Signed-off-by: Alex Deucher 
Reviewed-by: Luben Tuikov 
---
 drivers/gpu/drm/amd/amdgpu/Makefile|  3 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c | 67 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h | 34 +++
 3 files changed, 103 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h

diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile 
b/drivers/gpu/drm/amd/amdgpu/Makefile
index c56320e78c0e1f..7d292485ca7cf2 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -57,7 +57,8 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \
amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \
amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \
-   amdgpu_fw_attestation.o amdgpu_securedisplay.o amdgpu_hdp.o
+   amdgpu_fw_attestation.o amdgpu_securedisplay.o amdgpu_hdp.o \
+   amdgpu_eeprom.o
 
 amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
new file mode 100644
index 00..10551660343278
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "amdgpu_eeprom.h"
+#include "amdgpu.h"
+
+#define EEPROM_OFFSET_LENGTH 2
+
+int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
+  u16 slave_addr, u16 eeprom_addr,
+  u8 *eeprom_buf, u16 bytes, bool read)
+{
+   u8 eeprom_offset_buf[2];
+   u16 bytes_transferred;
+   struct i2c_msg msgs[] = {
+   {
+   .addr = slave_addr,
+   .flags = 0,
+   .len = EEPROM_OFFSET_LENGTH,
+   .buf = eeprom_offset_buf,
+   },
+   {
+   .addr = slave_addr,
+   .flags = read ? I2C_M_RD: 0,
+   .len = bytes,
+   .buf = eeprom_buf,
+   }
+   };
+   int r;
+
+   msgs[0].buf[0] = ((eeprom_addr >> 8) & 0xff);
+   msgs[0].buf[1] = (eeprom_addr & 0xff);
+
+   while (msgs[1].len) {
+   r = i2c_transfer(i2c_adap, msgs, ARRAY_SIZE(msgs));
+   if (r <= 0)
+   return r;
+   bytes_transferred = r - EEPROM_OFFSET_LENGTH;
+   eeprom_addr += bytes_transferred;
+   msgs[0].buf[0] = ((eeprom_addr >> 8) & 0xff);
+   msgs[0].buf[1] = (eeprom_addr & 0xff);
+   msgs[1].buf += bytes_transferred;
+   msgs[1].len -= bytes_transferred;
+   }
+
+   return 0;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h
new file mode 100644
index 00..9301e5678910ad
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of 

[PATCH 25/43] drm/amdgpu: RAS: EEPROM --> RAS

2021-06-21 Thread Luben Tuikov
In amdgpu_ras_eeprom.c--the interface from RAS to
EEPROM, rename macros from EEPROM to RAS, to
indicate that the quantities and objects are RAS
specific, not EEPROM. We can decrease the RAS
table, or put it in different offset of EEPROM as
needed in the future.

Remove EEPROM_ADDRESS_SIZE macro definition, equal
to 2, from the file and calculations, as that
quantity is computed and added on the stack,
in the lower layer, amdgpu_eeprom_xfer().

Cc: Jean Delvare 
Cc: Alexander Deucher 
Cc: Andrey Grodzovsky 
Cc: Lijo Lazar 
Cc: Stanley Yang 
Cc: Hawking Zhang 
Signed-off-by: Luben Tuikov 
Acked-by: Alexander Deucher 
---
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c| 103 +-
 1 file changed, 50 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 3ef38b90fc3a83..d3678706bb736d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -37,26 +37,25 @@
 /*
  * The 2 macros bellow represent the actual size in bytes that
  * those entities occupy in the EEPROM memory.
- * EEPROM_TABLE_RECORD_SIZE is different than sizeof(eeprom_table_record) which
+ * RAS_TABLE_RECORD_SIZE is different than sizeof(eeprom_table_record) which
  * uses uint64 to store 6b fields such as retired_page.
  */
-#define EEPROM_TABLE_HEADER_SIZE 20
-#define EEPROM_TABLE_RECORD_SIZE 24
-
-#define EEPROM_ADDRESS_SIZE 0x2
+#define RAS_TABLE_HEADER_SIZE   20
+#define RAS_TABLE_RECORD_SIZE   24
 
 /* Table hdr is 'AMDR' */
-#define EEPROM_TABLE_HDR_VAL 0x414d4452
-#define EEPROM_TABLE_VER 0x0001
+#define RAS_TABLE_HDR_VAL   0x414d4452
+#define RAS_TABLE_VER   0x0001
 
 /* Bad GPU tag ‘BADG’ */
-#define EEPROM_TABLE_HDR_BAD 0x42414447
+#define RAS_TABLE_HDR_BAD   0x42414447
 
-/* Assume 2-Mbit size */
-#define EEPROM_SIZE_BYTES   (256 * 1024)
-#define EEPROM_HDR_START0
-#define EEPROM_RECORD_START (EEPROM_HDR_START + EEPROM_TABLE_HEADER_SIZE)
-#define EEPROM_MAX_RECORD_NUM   ((EEPROM_SIZE_BYTES - 
EEPROM_TABLE_HEADER_SIZE) / EEPROM_TABLE_RECORD_SIZE)
+/* Assume 2-Mbit size EEPROM and take up the whole space. */
+#define RAS_TBL_SIZE_BYTES  (256 * 1024)
+#define RAS_HDR_START   0
+#define RAS_RECORD_START(RAS_HDR_START + RAS_TABLE_HEADER_SIZE)
+#define RAS_MAX_RECORD_NUM  ((RAS_TBL_SIZE_BYTES - RAS_TABLE_HEADER_SIZE) \
+/ RAS_TABLE_RECORD_SIZE)
 
 #define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, 
eeprom_control))->adev
 
@@ -153,8 +152,8 @@ static int __update_table_header(struct 
amdgpu_ras_eeprom_control *control,
/* i2c may be unstable in gpu reset */
down_read(>reset_sem);
ret = amdgpu_eeprom_xfer(>pm.smu_i2c,
-control->i2c_address + EEPROM_HDR_START,
-buff, EEPROM_TABLE_HEADER_SIZE, false);
+control->i2c_address + RAS_HDR_START,
+buff, RAS_TABLE_HEADER_SIZE, false);
up_read(>reset_sem);
 
if (ret < 1)
@@ -236,11 +235,11 @@ static int amdgpu_ras_eeprom_correct_header_tag(
struct amdgpu_ras_eeprom_control *control,
uint32_t header)
 {
-   unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE];
+   unsigned char buff[RAS_TABLE_HEADER_SIZE];
struct amdgpu_ras_eeprom_table_header *hdr = >tbl_hdr;
int ret = 0;
 
-   memset(buff, 0, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE);
+   memset(buff, 0, RAS_TABLE_HEADER_SIZE);
 
mutex_lock(>tbl_mutex);
hdr->header = header;
@@ -252,20 +251,20 @@ static int amdgpu_ras_eeprom_correct_header_tag(
 
 int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
 {
-   unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 
0 };
+   unsigned char buff[RAS_TABLE_HEADER_SIZE] = { 0 };
struct amdgpu_ras_eeprom_table_header *hdr = >tbl_hdr;
int ret = 0;
 
mutex_lock(>tbl_mutex);
 
-   hdr->header = EEPROM_TABLE_HDR_VAL;
-   hdr->version = EEPROM_TABLE_VER;
-   hdr->first_rec_offset = EEPROM_RECORD_START;
-   hdr->tbl_size = EEPROM_TABLE_HEADER_SIZE;
+   hdr->header = RAS_TABLE_HDR_VAL;
+   hdr->version = RAS_TABLE_VER;
+   hdr->first_rec_offset = RAS_RECORD_START;
+   hdr->tbl_size = RAS_TABLE_HEADER_SIZE;
 
control->tbl_byte_sum = 0;
__update_tbl_checksum(control, NULL, 0, 0);
-   control->next_addr = EEPROM_RECORD_START;
+   control->next_addr = RAS_RECORD_START;
 
ret = __update_table_header(control, buff);
 
@@ -280,7 +279,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control 
*control,
 {
int ret = 0;
struct amdgpu_device *adev = to_amdgpu_device(control);
-   unsigned char 

[PATCH 01/43] drm/amdgpu: add a mutex for the smu11 i2c bus (v2)

2021-06-21 Thread Luben Tuikov
From: Alex Deucher 

So we lock software as well as hardware access to the bus.

v2: fix mutex handling.

Signed-off-by: Alex Deucher 
Reviewed-by: Luben Tuikov 
---
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 19 +--
 drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h|  1 +
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c 
b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index 5c7d769aee3fba..1d8f6d5180e099 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -584,12 +584,11 @@ static void lock_bus(struct i2c_adapter *i2c, unsigned 
int flags)
 {
struct amdgpu_device *adev = to_amdgpu_device(i2c);
 
-   if (!smu_v11_0_i2c_bus_lock(i2c)) {
+   mutex_lock(>pm.smu_i2c_mutex);
+   if (!smu_v11_0_i2c_bus_lock(i2c))
DRM_ERROR("Failed to lock the bus from SMU");
-   return;
-   }
-
-   adev->pm.bus_locked = true;
+   else
+   adev->pm.bus_locked = true;
 }
 
 static int trylock_bus(struct i2c_adapter *i2c, unsigned int flags)
@@ -602,12 +601,11 @@ static void unlock_bus(struct i2c_adapter *i2c, unsigned 
int flags)
 {
struct amdgpu_device *adev = to_amdgpu_device(i2c);
 
-   if (!smu_v11_0_i2c_bus_unlock(i2c)) {
+   if (!smu_v11_0_i2c_bus_unlock(i2c))
DRM_ERROR("Failed to unlock the bus from SMU");
-   return;
-   }
-
-   adev->pm.bus_locked = false;
+   else
+   adev->pm.bus_locked = false;
+   mutex_unlock(>pm.smu_i2c_mutex);
 }
 
 static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = {
@@ -665,6 +663,7 @@ int smu_v11_0_i2c_control_init(struct i2c_adapter *control)
struct amdgpu_device *adev = to_amdgpu_device(control);
int res;
 
+   mutex_init(>pm.smu_i2c_mutex);
control->owner = THIS_MODULE;
control->class = I2C_CLASS_SPD;
control->dev.parent = >pdev->dev;
diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h 
b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
index f6e0e7d8a00771..d03e6fa2bf1adf 100644
--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
@@ -450,6 +450,7 @@ struct amdgpu_pm {
 
/* Used for I2C access to various EEPROMs on relevant ASICs */
struct i2c_adapter smu_i2c;
+   struct mutexsmu_i2c_mutex;
struct list_headpm_attr_list;
 };
 
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH v2 umr 3/3] Enhance printing of page tables in AI+

2021-06-21 Thread Joseph Greathouse
Pulls print functions for GPUVM page tables on AI+ chips into their
own set of generalized functions, so that we don't have subtly
different printouts for different layers.

Explicitly prints PDEs with P bit (which makes it a PTE) and makes
the PTE with F bit set (further, which makes it a PDE) properly
indent the next layer of the print.

Prints remaining fields from the PTE and PDE printouts, such as
read/write/execute bits and MTYPE from PTE.

v2: Correctly handle printing translate-further PTEs

Signed-off-by: Joseph Greathouse 
---
 src/lib/read_vram.c | 184 ++--
 1 file changed, 127 insertions(+), 57 deletions(-)

diff --git a/src/lib/read_vram.c b/src/lib/read_vram.c
index 2998873..bea1232 100644
--- a/src/lib/read_vram.c
+++ b/src/lib/read_vram.c
@@ -415,6 +415,112 @@ static pte_fields_ai_t decode_pte_entry_ai(uint64_t 
pte_entry)
return pte_fields;
 }
 
+static void print_pde_fields_ai(struct umr_asic *asic,
+   pde_fields_ai_t pde_fields)
+{
+   asic->mem_funcs.vm_message(
+   ", PBA==0x%012" PRIx64 ", V=%" PRIu64
+   ", S=%" PRIu64 ", C=%" PRIu64
+   ", P=%" PRIu64 ", FS=%" PRIu64 "\n",
+   pde_fields.pte_base_addr,
+   pde_fields.valid,
+   pde_fields.system,
+   pde_fields.coherent,
+   pde_fields.pte,
+   pde_fields.frag_size);
+}
+static void print_base_ai(struct umr_asic *asic,
+ uint64_t pde_entry, uint64_t address,
+ uint64_t va_mask, pde_fields_ai_t pde_fields,
+ int is_base_not_pde)
+{
+   if (is_base_not_pde)
+   asic->mem_funcs.vm_message("BASE");
+   else
+   asic->mem_funcs.vm_message("PDE");
+   asic->mem_funcs.vm_message("=0x%016" PRIx64 ", VA=0x%012" PRIx64,
+   pde_entry,
+   address & va_mask);
+   print_pde_fields_ai(asic, pde_fields);
+}
+
+static void print_pde_ai(struct umr_asic *asic,
+   const char * indentation, int pde_cnt,
+   int page_table_depth, uint64_t prev_addr,
+   uint64_t pde_idx, uint64_t pde_entry, uint64_t address,
+   uint64_t va_mask, pde_fields_ai_t pde_fields)
+{
+   asic->mem_funcs.vm_message("%s ", [18-pde_cnt*3]);
+   if (pde_fields.further)
+   asic->mem_funcs.vm_message("PTE-FURTHER");
+   else
+   asic->mem_funcs.vm_message("PDE%d", page_table_depth - pde_cnt);
+
+   asic->mem_funcs.vm_message("@{0x%" PRIx64 "/%" PRIx64
+   "}=0x%016" PRIx64 ", VA=0x%012" PRIx64,
+   prev_addr,
+   pde_idx,
+   pde_entry,
+   address & va_mask);
+   print_pde_fields_ai(asic, pde_fields);
+}
+
+static void print_pte_ai(struct umr_asic *asic,
+   const char * indentation, int pde_cnt, uint64_t prev_addr,
+   uint64_t pte_idx, uint64_t pte_entry, uint64_t address,
+   uint64_t va_mask, pte_fields_ai_t pte_fields)
+{
+   if (asic == NULL) {
+   asic->mem_funcs.vm_message("\\-> PTE");
+   } else {
+   asic->mem_funcs.vm_message("%s ",
+   [18-pde_cnt*3]);
+   if (pte_fields.pde)
+   asic->mem_funcs.vm_message("PDE0-as-PTE");
+   else
+   asic->mem_funcs.vm_message("PTE");
+   asic->mem_funcs.vm_message("@{0x%" PRIx64 "/%" PRIx64"}",
+   prev_addr,
+   pte_idx);
+   }
+   asic->mem_funcs.vm_message("=0x%016" PRIx64 ", VA=0x%012" PRIx64
+   ", PBA==0x%012" PRIx64 ", V=%" PRIu64
+   ", S=%" PRIu64 ", C=%" PRIu64 ", Z=%" PRIu64
+   ", X=%" PRIu64 ", R=%" PRIu64 ", W=%" PRIu64
+   ", FS=%" PRIu64 ", T=%" PRIu64 ", MTYPE=",
+   pte_entry,
+   address & va_mask,
+   pte_fields.page_base_addr,
+   pte_fields.valid,
+   pte_fields.system,
+   pte_fields.coherent,
+   pte_fields.tmz,
+   pte_fields.execute,
+   pte_fields.read,
+   pte_fields.write,
+   pte_fields.fragment,
+   pte_fields.prt,
+   pte_fields.mtype);
+   switch (pte_fields.mtype) {
+   case 0:
+   asic->mem_funcs.vm_message("NC\n");
+   break;
+   case 1:
+   asic->mem_funcs.vm_message("RW\n");
+   break;
+   case 2:
+

[PATCH 10/10] drm/amdkfd: protect svm_bo ref in case prange has forked

2021-06-21 Thread Alex Sierra
Keep track of all the pages inside of pranges referenced to
the same svm_bo. This is done, by using the ref count inside this object.
This makes sure the object has freed after the last prange is not longer
at any GPU. Including references shared between a parent and child during
a fork.

Signed-off-by: Alex Sierra 
Change-Id: Ibfe5efbfed28c2d7681fe091264a5d0d5f3657b2
---
 drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 10 --
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 10 +-
 drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 10 +-
 3 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index acb9f64577a0..c8ca3252cbc2 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -245,7 +245,7 @@ svm_migrate_get_vram_page(struct svm_range *prange, 
unsigned long pfn)
struct page *page;
 
page = pfn_to_page(pfn);
-   page->zone_device_data = prange;
+   page->zone_device_data = prange->svm_bo;
get_page(page);
lock_page(page);
 }
@@ -336,6 +336,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct 
svm_range *prange,
svm_migrate_get_vram_page(prange, migrate->dst[i]);
migrate->dst[i] = migrate_pfn(migrate->dst[i]);
migrate->dst[i] |= MIGRATE_PFN_LOCKED;
+   svm_range_bo_ref(prange->svm_bo);
}
if (migrate->dst[i] & MIGRATE_PFN_VALID) {
spage = migrate_pfn_to_page(migrate->src[i]);
@@ -540,7 +541,12 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t 
best_loc,
 
 static void svm_migrate_page_free(struct page *page)
 {
-   /* Keep this function to avoid warning */
+   struct svm_range_bo *svm_bo = page->zone_device_data;
+
+   if (svm_bo) {
+   pr_debug("svm_bo ref left: %d\n", kref_read(_bo->kref));
+   svm_range_bo_unref(svm_bo);
+   }
 }
 
 static int
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index ebc1ae7e5193..4b5fc2375641 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -309,14 +309,6 @@ static bool svm_bo_ref_unless_zero(struct svm_range_bo 
*svm_bo)
return true;
 }
 
-static struct svm_range_bo *svm_range_bo_ref(struct svm_range_bo *svm_bo)
-{
-   if (svm_bo)
-   kref_get(_bo->kref);
-
-   return svm_bo;
-}
-
 static void svm_range_bo_release(struct kref *kref)
 {
struct svm_range_bo *svm_bo;
@@ -355,7 +347,7 @@ static void svm_range_bo_release(struct kref *kref)
kfree(svm_bo);
 }
 
-static void svm_range_bo_unref(struct svm_range_bo *svm_bo)
+void svm_range_bo_unref(struct svm_range_bo *svm_bo)
 {
if (!svm_bo)
return;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index 27fbe1936493..21f693767a0d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -150,6 +150,14 @@ static inline void svm_range_unlock(struct svm_range 
*prange)
mutex_unlock(>lock);
 }
 
+static inline struct svm_range_bo *svm_range_bo_ref(struct svm_range_bo 
*svm_bo)
+{
+   if (svm_bo)
+   kref_get(_bo->kref);
+
+   return svm_bo;
+}
+
 int svm_range_list_init(struct kfd_process *p);
 void svm_range_list_fini(struct kfd_process *p);
 int svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start,
@@ -178,7 +186,7 @@ void svm_range_dma_unmap(struct device *dev, dma_addr_t 
*dma_addr,
 void svm_range_free_dma_mappings(struct svm_range *prange);
 void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm,
void *owner);
-
+void svm_range_bo_unref(struct svm_range_bo *svm_bo);
 #else
 
 struct kfd_process;
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 05/10] drm/amdkfd: classify and map mixed svm range pages in GPU

2021-06-21 Thread Alex Sierra
[Why]
svm ranges can have mixed pages from device or system memory.
A good example is, after a prange has been allocated in VRAM and a
copy-on-write is triggered by a fork. This invalidates some pages
inside the prange. Endding up in mixed pages.

[How]
By classifying each page inside a prange, based on its type. Device or
system memory, during dma mapping call. If page corresponds
to VRAM domain, a flag is set to its dma_addr entry for each GPU.
Then, at the GPU page table mapping. All group of contiguous pages within
the same type are mapped with their proper pte flags.

v2:
Instead of using ttm_res to calculate vram pfns in the svm_range. It is now
done by setting the vram real physical address into drm_addr array.
This makes more flexible VRAM management, plus removes the need to have
a BO reference in the svm_range.

v3:
Remove mapping member from svm_range

Signed-off-by: Alex Sierra 
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 73 ++--
 drivers/gpu/drm/amd/amdkfd/kfd_svm.h |  2 +-
 2 files changed, 47 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 2b4318646a75..3b05bc270732 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -119,11 +119,12 @@ static void svm_range_remove_notifier(struct svm_range 
*prange)
 }
 
 static int
-svm_range_dma_map_dev(struct device *dev, dma_addr_t **dma_addr,
+svm_range_dma_map_dev(struct amdgpu_device *adev, dma_addr_t **dma_addr,
  unsigned long *hmm_pfns, uint64_t npages)
 {
enum dma_data_direction dir = DMA_BIDIRECTIONAL;
dma_addr_t *addr = *dma_addr;
+   struct device *dev = adev->dev;
struct page *page;
int i, r;
 
@@ -141,6 +142,14 @@ svm_range_dma_map_dev(struct device *dev, dma_addr_t 
**dma_addr,
dma_unmap_page(dev, addr[i], PAGE_SIZE, dir);
 
page = hmm_pfn_to_page(hmm_pfns[i]);
+   if (is_zone_device_page(page)) {
+   addr[i] = (hmm_pfns[i] << PAGE_SHIFT) +
+  adev->vm_manager.vram_base_offset -
+  adev->kfd.dev->pgmap.range.start;
+   addr[i] |= SVM_RANGE_VRAM_DOMAIN;
+   pr_debug("vram address detected: 0x%llx\n", addr[i]);
+   continue;
+   }
addr[i] = dma_map_page(dev, page, 0, PAGE_SIZE, dir);
r = dma_mapping_error(dev, addr[i]);
if (r) {
@@ -175,7 +184,7 @@ svm_range_dma_map(struct svm_range *prange, unsigned long 
*bitmap,
}
adev = (struct amdgpu_device *)pdd->dev->kgd;
 
-   r = svm_range_dma_map_dev(adev->dev, >dma_addr[gpuidx],
+   r = svm_range_dma_map_dev(adev, >dma_addr[gpuidx],
  hmm_pfns, prange->npages);
if (r)
break;
@@ -1003,21 +1012,22 @@ svm_range_split_by_granularity(struct kfd_process *p, 
struct mm_struct *mm,
 }
 
 static uint64_t
-svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange)
+svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange,
+   int domain)
 {
struct amdgpu_device *bo_adev;
uint32_t flags = prange->flags;
uint32_t mapping_flags = 0;
uint64_t pte_flags;
-   bool snoop = !prange->ttm_res;
+   bool snoop = (domain != SVM_RANGE_VRAM_DOMAIN);
bool coherent = flags & KFD_IOCTL_SVM_FLAG_COHERENT;
 
-   if (prange->svm_bo && prange->ttm_res)
+   if (domain == SVM_RANGE_VRAM_DOMAIN)
bo_adev = amdgpu_ttm_adev(prange->svm_bo->bo->tbo.bdev);
 
switch (adev->asic_type) {
case CHIP_ARCTURUS:
-   if (prange->svm_bo && prange->ttm_res) {
+   if (domain == SVM_RANGE_VRAM_DOMAIN) {
if (bo_adev == adev) {
mapping_flags |= coherent ?
AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW;
@@ -1032,7 +1042,7 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, 
struct svm_range *prange)
}
break;
case CHIP_ALDEBARAN:
-   if (prange->svm_bo && prange->ttm_res) {
+   if (domain == SVM_RANGE_VRAM_DOMAIN) {
if (bo_adev == adev) {
mapping_flags |= coherent ?
AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW;
@@ -1061,14 +1071,14 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, 
struct svm_range *prange)
mapping_flags |= AMDGPU_VM_PAGE_EXECUTABLE;
 
pte_flags = AMDGPU_PTE_VALID;
-   pte_flags |= prange->ttm_res ? 0 : AMDGPU_PTE_SYSTEM;
+   pte_flags |= (domain == SVM_RANGE_VRAM_DOMAIN) ? 0 : AMDGPU_PTE_SYSTEM;

[PATCH 02/10] drm/amdkfd: add owner ref param to get hmm pages

2021-06-21 Thread Alex Sierra
The parameter is used in the dev_private_owner to decide if device
pages in the range require to be migrated back to system memory, based
if they are or not in the same memory domain.
In this case, this reference could come from the same memory domain
with devices connected to the same hive.

Signed-off-by: Alex Sierra 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c  | 3 ++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h  | 2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +-
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c| 4 ++--
 4 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
index 2741c28ff1b5..378c238c2099 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
@@ -160,7 +160,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier 
*notifier,
   struct mm_struct *mm, struct page **pages,
   uint64_t start, uint64_t npages,
   struct hmm_range **phmm_range, bool readonly,
-  bool mmap_locked)
+  bool mmap_locked, void *owner)
 {
struct hmm_range *hmm_range;
unsigned long timeout;
@@ -185,6 +185,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier 
*notifier,
hmm_range->hmm_pfns = pfns;
hmm_range->start = start;
hmm_range->end = start + npages * PAGE_SIZE;
+   hmm_range->dev_private_owner = owner;
 
/* Assuming 512MB takes maxmium 1 second to fault page address */
timeout = max(npages >> 17, 1ULL) * HMM_RANGE_DEFAULT_TIMEOUT;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
index 7f7d37a457c3..14a3c1864085 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
@@ -34,7 +34,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier 
*notifier,
   struct mm_struct *mm, struct page **pages,
   uint64_t start, uint64_t npages,
   struct hmm_range **phmm_range, bool readonly,
-  bool mmap_locked);
+  bool mmap_locked, void *owner);
 int amdgpu_hmm_range_get_pages_done(struct hmm_range *hmm_range);
 
 #if defined(CONFIG_HMM_MIRROR)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 7e7d8330d64b..c13f7fbfc070 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -709,7 +709,7 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, 
struct page **pages)
readonly = amdgpu_ttm_tt_is_readonly(ttm);
r = amdgpu_hmm_range_get_pages(>notifier, mm, pages, start,
   ttm->num_pages, >range, readonly,
-  false);
+  false, NULL);
 out_putmm:
mmput(mm);
 
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index b665e9ff77e3..b939f353ac8c 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1392,7 +1392,7 @@ static int svm_range_validate_and_map(struct mm_struct 
*mm,
r = amdgpu_hmm_range_get_pages(>notifier, mm, NULL,
   prange->start << PAGE_SHIFT,
   prange->npages, _range,
-  false, true);
+  false, true, NULL);
if (r) {
pr_debug("failed %d to get svm range pages\n", r);
goto unreserve_out;
@@ -2657,7 +2657,7 @@ void svm_range_prefault(struct svm_range *prange, struct 
mm_struct *mm)
r = amdgpu_hmm_range_get_pages(>notifier, mm, NULL,
   prange->start << PAGE_SHIFT,
   prange->npages, _range,
-  false, true);
+  false, true, NULL);
if (!r) {
amdgpu_hmm_range_get_pages_done(hmm_range);
prange->validated_once = true;
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 06/10] drm/amdkfd: skip invalid pages during migrations

2021-06-21 Thread Alex Sierra
Invalid pages can be the result of pages that have been migrated
already due to copy-on-write procedure or pages that were never
migrated to VRAM in first place. This is not an issue anymore,
as pranges now support mixed memory domains (CPU/GPU).

Signed-off-by: Alex Sierra 
Reviewed-by: Felix Kuehling 
---
 drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 38 +++-
 1 file changed, 18 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index b298aa8dea4d..6fd68528c425 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -419,7 +419,6 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct 
svm_range *prange,
size_t size;
void *buf;
int r = -ENOMEM;
-   int retry = 0;
 
memset(, 0, sizeof(migrate));
migrate.vma = vma;
@@ -438,7 +437,6 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct 
svm_range *prange,
migrate.dst = migrate.src + npages;
scratch = (dma_addr_t *)(migrate.dst + npages);
 
-retry:
r = migrate_vma_setup();
if (r) {
pr_debug("failed %d prepare migrate svms 0x%p [0x%lx 0x%lx]\n",
@@ -446,17 +444,9 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct 
svm_range *prange,
goto out_free;
}
if (migrate.cpages != npages) {
-   pr_debug("collect 0x%lx/0x%llx pages, retry\n", migrate.cpages,
+   pr_debug("Partial migration. 0x%lx/0x%llx pages can be 
migrated\n",
+migrate.cpages,
 npages);
-   migrate_vma_finalize();
-   if (retry++ >= 3) {
-   r = -ENOMEM;
-   pr_debug("failed %d migrate svms 0x%p [0x%lx 0x%lx]\n",
-r, prange->svms, prange->start, prange->last);
-   goto out_free;
-   }
-
-   goto retry;
}
 
if (migrate.cpages) {
@@ -547,9 +537,8 @@ static void svm_migrate_page_free(struct page *page)
 static int
 svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
struct migrate_vma *migrate, struct dma_fence **mfence,
-   dma_addr_t *scratch)
+   dma_addr_t *scratch, uint64_t npages)
 {
-   uint64_t npages = migrate->cpages;
struct device *dev = adev->dev;
uint64_t *src;
dma_addr_t *dst;
@@ -566,15 +555,23 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, 
struct svm_range *prange,
src = (uint64_t *)(scratch + npages);
dst = scratch;
 
-   for (i = 0, j = 0; i < npages; i++, j++, addr += PAGE_SIZE) {
+   for (i = 0, j = 0; i < npages; i++, addr += PAGE_SIZE) {
struct page *spage;
 
spage = migrate_pfn_to_page(migrate->src[i]);
-   if (!spage) {
-   pr_debug("failed get spage svms 0x%p [0x%lx 0x%lx]\n",
+   if (!spage || !is_zone_device_page(spage)) {
+   pr_debug("invalid page. Could be in CPU already svms 
0x%p [0x%lx 0x%lx]\n",
 prange->svms, prange->start, prange->last);
-   r = -ENOMEM;
-   goto out_oom;
+   if (j) {
+   r = svm_migrate_copy_memory_gart(adev, dst + i 
- j,
+src + i - j, j,
+
FROM_VRAM_TO_RAM,
+mfence);
+   if (r)
+   goto out_oom;
+   j = 0;
+   }
+   continue;
}
src[i] = svm_migrate_addr(adev, spage);
if (i > 0 && src[i] != src[i - 1] + PAGE_SIZE) {
@@ -607,6 +604,7 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct 
svm_range *prange,
 
migrate->dst[i] = migrate_pfn(page_to_pfn(dpage));
migrate->dst[i] |= MIGRATE_PFN_LOCKED;
+   j++;
}
 
r = svm_migrate_copy_memory_gart(adev, dst + i - j, src + i - j, j,
@@ -664,7 +662,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct 
svm_range *prange,
 
if (migrate.cpages) {
r = svm_migrate_copy_to_ram(adev, prange, , ,
-   scratch);
+   scratch, npages);
migrate_vma_pages();
svm_migrate_copy_done(adev, mfence);
migrate_vma_finalize();
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org

[PATCH 07/10] drm/amdkfd: skip migration for pages already in VRAM

2021-06-21 Thread Alex Sierra
Migration skipped for pages that are already in VRAM
domain. These could be the result of previous partial
migrations to SYS RAM, and prefetch back to VRAM.
Ex. Coherent pages in VRAM that were not written/invalidated after
a copy-on-write.

Signed-off-by: Alex Sierra 
---
 drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 6fd68528c425..8a3f21d76915 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -329,14 +329,15 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, 
struct svm_range *prange,
for (i = j = 0; i < npages; i++) {
struct page *spage;
 
-   dst[i] = vram_addr + (j << PAGE_SHIFT);
-   migrate->dst[i] = svm_migrate_addr_to_pfn(adev, dst[i]);
-   svm_migrate_get_vram_page(prange, migrate->dst[i]);
-
-   migrate->dst[i] = migrate_pfn(migrate->dst[i]);
-   migrate->dst[i] |= MIGRATE_PFN_LOCKED;
-
-   if (migrate->src[i] & MIGRATE_PFN_VALID) {
+   spage = migrate_pfn_to_page(migrate->src[i]);
+   if (spage && !is_zone_device_page(spage)) {
+   dst[i] = vram_addr + (j << PAGE_SHIFT);
+   migrate->dst[i] = svm_migrate_addr_to_pfn(adev, dst[i]);
+   svm_migrate_get_vram_page(prange, migrate->dst[i]);
+   migrate->dst[i] = migrate_pfn(migrate->dst[i]);
+   migrate->dst[i] |= MIGRATE_PFN_LOCKED;
+   }
+   if (migrate->dst[i] & MIGRATE_PFN_VALID) {
spage = migrate_pfn_to_page(migrate->src[i]);
src[i] = dma_map_page(dev, spage, 0, PAGE_SIZE,
  DMA_TO_DEVICE);
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 03/10] drm/amdkfd: set owner ref to svm range prefault

2021-06-21 Thread Alex Sierra
svm_range_prefault is called right before migrations to VRAM,
to make sure pages are resident in system memory before the migration.
With partial migrations, this reference is used by hmm range get pages
to avoid migrating pages that are already in the same VRAM domain.

Signed-off-by: Alex Sierra 
---
 drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 2 +-
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 5 +++--
 drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 3 ++-
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 11f7f590c6ec..b298aa8dea4d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -512,7 +512,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t 
best_loc,
 prange->start, prange->last, best_loc);
 
/* FIXME: workaround for page locking bug with invalid pages */
-   svm_range_prefault(prange, mm);
+   svm_range_prefault(prange, mm, SVM_ADEV_PGMAP_OWNER(adev));
 
start = prange->start << PAGE_SHIFT;
end = (prange->last + 1) << PAGE_SHIFT;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index b939f353ac8c..54f47b09b14a 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -2646,7 +2646,8 @@ svm_range_best_prefetch_location(struct svm_range *prange)
 /* FIXME: This is a workaround for page locking bug when some pages are
  * invalid during migration to VRAM
  */
-void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm)
+void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm,
+   void *owner)
 {
struct hmm_range *hmm_range;
int r;
@@ -2657,7 +2658,7 @@ void svm_range_prefault(struct svm_range *prange, struct 
mm_struct *mm)
r = amdgpu_hmm_range_get_pages(>notifier, mm, NULL,
   prange->start << PAGE_SHIFT,
   prange->npages, _range,
-  false, true, NULL);
+  false, true, owner);
if (!r) {
amdgpu_hmm_range_get_pages_done(hmm_range);
prange->validated_once = true;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index 4297250f259d..08542fe39303 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -176,7 +176,8 @@ void schedule_deferred_list_work(struct svm_range_list 
*svms);
 void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr,
 unsigned long offset, unsigned long npages);
 void svm_range_free_dma_mappings(struct svm_range *prange);
-void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm);
+void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm,
+   void *owner);
 
 #else
 
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 01/10] drm/amdkfd: device pgmap owner at the svm migrate init

2021-06-21 Thread Alex Sierra
pgmap owner member at the svm migrate init could be referenced
to either adev or hive, depending on device topology.

Signed-off-by: Alex Sierra 
---
 drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 6 +++---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 3 +++
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index fd8f544f0de2..11f7f590c6ec 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -426,7 +426,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct 
svm_range *prange,
migrate.start = start;
migrate.end = end;
migrate.flags = MIGRATE_VMA_SELECT_SYSTEM;
-   migrate.pgmap_owner = adev;
+   migrate.pgmap_owner = SVM_ADEV_PGMAP_OWNER(adev);
 
size = 2 * sizeof(*migrate.src) + sizeof(uint64_t) + sizeof(dma_addr_t);
size *= npages;
@@ -641,7 +641,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct 
svm_range *prange,
migrate.start = start;
migrate.end = end;
migrate.flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
-   migrate.pgmap_owner = adev;
+   migrate.pgmap_owner = SVM_ADEV_PGMAP_OWNER(adev);
 
size = 2 * sizeof(*migrate.src) + sizeof(uint64_t) + sizeof(dma_addr_t);
size *= npages;
@@ -907,7 +907,7 @@ int svm_migrate_init(struct amdgpu_device *adev)
pgmap->range.start = res->start;
pgmap->range.end = res->end;
pgmap->ops = _migrate_pgmap_ops;
-   pgmap->owner = adev;
+   pgmap->owner = SVM_ADEV_PGMAP_OWNER(adev);
pgmap->flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE;
r = devm_memremap_pages(adev->dev, pgmap);
if (IS_ERR(r)) {
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index 573f984b81fe..4297250f259d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -35,6 +35,9 @@
 #include "amdgpu.h"
 #include "kfd_priv.h"
 
+#define SVM_ADEV_PGMAP_OWNER(adev)\
+   ((adev)->hive ? (void *)(adev)->hive : (void *)(adev))
+
 struct svm_range_bo {
struct amdgpu_bo*bo;
struct kref kref;
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 09/10] drm/amdkfd: partially actual_loc removed

2021-06-21 Thread Alex Sierra
actual_loc should not be used anymore, as pranges
could have mixed locations (VRAM & SYSRAM) at the
same time.

Signed-off-by: Alex Sierra 
---
 drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 12 +---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 71 ++--
 2 files changed, 29 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index f71f8d7e2b72..acb9f64577a0 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -501,12 +501,6 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t 
best_loc,
struct amdgpu_device *adev;
int r = 0;
 
-   if (prange->actual_loc == best_loc) {
-   pr_debug("svms 0x%p [0x%lx 0x%lx] already on best_loc 0x%x\n",
-prange->svms, prange->start, prange->last, best_loc);
-   return 0;
-   }
-
adev = svm_range_get_adev_by_id(prange, best_loc);
if (!adev) {
pr_debug("failed to get device by id 0x%x\n", best_loc);
@@ -791,11 +785,7 @@ int
 svm_migrate_to_vram(struct svm_range *prange, uint32_t best_loc,
struct mm_struct *mm)
 {
-   if  (!prange->actual_loc)
-   return svm_migrate_ram_to_vram(prange, best_loc, mm);
-   else
-   return svm_migrate_vram_to_vram(prange, best_loc, mm);
-
+   return svm_migrate_ram_to_vram(prange, best_loc, mm);
 }
 
 /**
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 3b05bc270732..ebc1ae7e5193 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1421,42 +1421,38 @@ static int svm_range_validate_and_map(struct mm_struct 
*mm,
 
svm_range_reserve_bos();
 
-   if (!prange->actual_loc) {
-   p = container_of(prange->svms, struct kfd_process, svms);
-   owner = kfd_svm_page_owner(p, find_first_bit(ctx.bitmap,
-   MAX_GPU_INSTANCE));
-   for_each_set_bit(idx, ctx.bitmap, MAX_GPU_INSTANCE) {
-   if (kfd_svm_page_owner(p, idx) != owner) {
-   owner = NULL;
-   break;
-   }
-   }
-   r = amdgpu_hmm_range_get_pages(>notifier, mm, NULL,
-  prange->start << PAGE_SHIFT,
-  prange->npages, _range,
-  false, true, owner);
-   if (r) {
-   pr_debug("failed %d to get svm range pages\n", r);
-   goto unreserve_out;
-   }
-
-   r = svm_range_dma_map(prange, ctx.bitmap,
- hmm_range->hmm_pfns);
-   if (r) {
-   pr_debug("failed %d to dma map range\n", r);
-   goto unreserve_out;
+   p = container_of(prange->svms, struct kfd_process, svms);
+   owner = kfd_svm_page_owner(p, find_first_bit(ctx.bitmap,
+   MAX_GPU_INSTANCE));
+   for_each_set_bit(idx, ctx.bitmap, MAX_GPU_INSTANCE) {
+   if (kfd_svm_page_owner(p, idx) != owner) {
+   owner = NULL;
+   break;
}
+   }
+   r = amdgpu_hmm_range_get_pages(>notifier, mm, NULL,
+  prange->start << PAGE_SHIFT,
+  prange->npages, _range,
+  false, true, owner);
+   if (r) {
+   pr_debug("failed %d to get svm range pages\n", r);
+   goto unreserve_out;
+   }
 
-   prange->validated_once = true;
+   r = svm_range_dma_map(prange, ctx.bitmap,
+ hmm_range->hmm_pfns);
+   if (r) {
+   pr_debug("failed %d to dma map range\n", r);
+   goto unreserve_out;
}
 
+   prange->validated_once = true;
+
svm_range_lock(prange);
-   if (!prange->actual_loc) {
-   if (amdgpu_hmm_range_get_pages_done(hmm_range)) {
-   pr_debug("hmm update the range, need validate again\n");
-   r = -EAGAIN;
-   goto unlock_out;
-   }
+   if (amdgpu_hmm_range_get_pages_done(hmm_range)) {
+   pr_debug("hmm update the range, need validate again\n");
+   r = -EAGAIN;
+   goto unlock_out;
}
if (!list_empty(>child_list)) {
pr_debug("range split by unmap in parallel, validate again\n");
@@ -2741,20 +2737,9 @@ svm_range_trigger_migration(struct mm_struct *mm, struct 
svm_range *prange,
*migrated = false;
best_loc = svm_range_best_prefetch_location(prange);
 

[PATCH 08/10] drm/amdkfd: add invalid pages debug at vram migration

2021-06-21 Thread Alex Sierra
This is for debug purposes only.
It conditionally generates partial migrations to test mixed
CPU/GPU memory domain pages in a prange easily.

Signed-off-by: Alex Sierra 
---
 drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 8a3f21d76915..f71f8d7e2b72 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -404,6 +404,20 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, 
struct svm_range *prange,
}
}
 
+#ifdef DEBUG_FORCE_MIXED_DOMAINS
+   for (i = 0, j = 0; i < npages; i += 4, j++) {
+   if (j & 1)
+   continue;
+   svm_migrate_put_vram_page(adev, dst[i]);
+   migrate->dst[i] = 0;
+   svm_migrate_put_vram_page(adev, dst[i + 1]);
+   migrate->dst[i + 1] = 0;
+   svm_migrate_put_vram_page(adev, dst[i + 2]);
+   migrate->dst[i + 2] = 0;
+   svm_migrate_put_vram_page(adev, dst[i + 3]);
+   migrate->dst[i + 3] = 0;
+   }
+#endif
 out:
return r;
 }
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH 04/10] drm/amdgpu: get owner ref in validate and map

2021-06-21 Thread Alex Sierra
Get the proper owner reference for amdgpu_hmm_range_get_pages function.
This is useful for partial migrations. To avoid migrating back to
system memory, VRAM pages, that are accessible by all devices in the
same memory domain.
Ex. multiple devices in the same hive.

Signed-off-by: Alex Sierra 
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 25 -
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 54f47b09b14a..2b4318646a75 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1313,6 +1313,17 @@ static void svm_range_unreserve_bos(struct 
svm_validate_context *ctx)
ttm_eu_backoff_reservation(>ticket, >validate_list);
 }
 
+static void *kfd_svm_page_owner(struct kfd_process *p, int32_t gpuidx)
+{
+   struct kfd_process_device *pdd;
+   struct amdgpu_device *adev;
+
+   pdd = kfd_process_device_from_gpuidx(p, gpuidx);
+   adev = (struct amdgpu_device *)pdd->dev->kgd;
+
+   return SVM_ADEV_PGMAP_OWNER(adev);
+}
+
 /*
  * Validation+GPU mapping with concurrent invalidation (MMU notifiers)
  *
@@ -1343,6 +1354,9 @@ static int svm_range_validate_and_map(struct mm_struct 
*mm,
 {
struct svm_validate_context ctx;
struct hmm_range *hmm_range;
+   struct kfd_process *p;
+   void *owner;
+   int32_t idx;
int r = 0;
 
ctx.process = container_of(prange->svms, struct kfd_process, svms);
@@ -1389,10 +1403,19 @@ static int svm_range_validate_and_map(struct mm_struct 
*mm,
svm_range_reserve_bos();
 
if (!prange->actual_loc) {
+   p = container_of(prange->svms, struct kfd_process, svms);
+   owner = kfd_svm_page_owner(p, find_first_bit(ctx.bitmap,
+   MAX_GPU_INSTANCE));
+   for_each_set_bit(idx, ctx.bitmap, MAX_GPU_INSTANCE) {
+   if (kfd_svm_page_owner(p, idx) != owner) {
+   owner = NULL;
+   break;
+   }
+   }
r = amdgpu_hmm_range_get_pages(>notifier, mm, NULL,
   prange->start << PAGE_SHIFT,
   prange->npages, _range,
-  false, true, NULL);
+  false, true, owner);
if (r) {
pr_debug("failed %d to get svm range pages\n", r);
goto unreserve_out;
-- 
2.32.0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH 03/10] drm/amdkfd: set owner ref to svm range prefault

2021-06-21 Thread Felix Kuehling

On 2021-06-21 12:04 p.m., Alex Sierra wrote:

svm_range_prefault is called right before migrations to VRAM,
to make sure pages are resident in system memory before the migration.
With partial migrations, this reference is used by hmm range get pages
to avoid migrating pages that are already in the same VRAM domain.

Signed-off-by: Alex Sierra 


Reviewed-by: Felix Kuehling 



---
  drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 2 +-
  drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 5 +++--
  drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 3 ++-
  3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 11f7f590c6ec..b298aa8dea4d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -512,7 +512,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t 
best_loc,
 prange->start, prange->last, best_loc);
  
  	/* FIXME: workaround for page locking bug with invalid pages */

-   svm_range_prefault(prange, mm);
+   svm_range_prefault(prange, mm, SVM_ADEV_PGMAP_OWNER(adev));
  
  	start = prange->start << PAGE_SHIFT;

end = (prange->last + 1) << PAGE_SHIFT;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index b939f353ac8c..54f47b09b14a 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -2646,7 +2646,8 @@ svm_range_best_prefetch_location(struct svm_range *prange)
  /* FIXME: This is a workaround for page locking bug when some pages are
   * invalid during migration to VRAM
   */
-void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm)
+void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm,
+   void *owner)
  {
struct hmm_range *hmm_range;
int r;
@@ -2657,7 +2658,7 @@ void svm_range_prefault(struct svm_range *prange, struct 
mm_struct *mm)
r = amdgpu_hmm_range_get_pages(>notifier, mm, NULL,
   prange->start << PAGE_SHIFT,
   prange->npages, _range,
-  false, true, NULL);
+  false, true, owner);
if (!r) {
amdgpu_hmm_range_get_pages_done(hmm_range);
prange->validated_once = true;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index 4297250f259d..08542fe39303 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -176,7 +176,8 @@ void schedule_deferred_list_work(struct svm_range_list 
*svms);
  void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr,
 unsigned long offset, unsigned long npages);
  void svm_range_free_dma_mappings(struct svm_range *prange);
-void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm);
+void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm,
+   void *owner);
  
  #else
  

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH] drm/amdgpu: fix amdgpu_preempt_mgr_new()

2021-06-21 Thread Deucher, Alexander
[Public]

I've dropped it from my tree in that case.

From: Christian König 
Sent: Monday, June 21, 2021 6:27 AM
To: Alex Deucher ; Kuehling, Felix 

Cc: David Airlie ; Pan, Xinhui ; 
kernel-janit...@vger.kernel.org ; Maling list 
- DRI developers ; amd-gfx list 
; Daniel Vetter ; Deucher, 
Alexander ; Dave Airlie ; 
Koenig, Christian ; Dan Carpenter 

Subject: Re: [PATCH] drm/amdgpu: fix amdgpu_preempt_mgr_new()

Am 18.06.21 um 23:18 schrieb Alex Deucher:
> On Fri, Jun 18, 2021 at 11:40 AM Felix Kuehling  
> wrote:
>> Am 2021-06-18 um 4:39 a.m. schrieb Christian König:
>>> Am 18.06.21 um 10:37 schrieb Dan Carpenter:
 There is a reversed if statement in amdgpu_preempt_mgr_new() so it
 always returns -ENOMEM.

 Fixes: 09b020bb05a5 ("Merge tag 'drm-misc-next-2021-06-09' of
 git://anongit.freedesktop.org/drm/drm-misc into drm-next")
 Signed-off-by: Dan Carpenter 
>>> Most be some fallout from merging it with the TTM changes.
>>>
>>> Anyway, patch is Reviewed-by: Christian König 
>> This is obviously not for amd-staging-drm-next. Christian, are you going
>> to apply it to the relevant branches?
> I've applied it to my drm-next branch.

I already pushed it to drm-misc-next last week.

Christian.

>
> Alex
>
>
>> Thanks,
>>Felix
>>
>>
>>> Thanks,
>>> Christian.
>>>
 ---
drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c
 b/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c
 index f6aff7ce5160..d02c8637f909 100644
 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c
 +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c
 @@ -71,7 +71,7 @@ static int amdgpu_preempt_mgr_new(struct
 ttm_resource_manager *man,
struct amdgpu_preempt_mgr *mgr = to_preempt_mgr(man);
  *res = kzalloc(sizeof(**res), GFP_KERNEL);
 -if (*res)
 +if (!*res)
return -ENOMEM;
  ttm_resource_init(tbo, place, *res);
>> ___
>> amd-gfx mailing list
>> amd-gfx@lists.freedesktop.org
>> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfxdata=04%7C01%7Calexander.deucher%40amd.com%7C096813db12f24172870508d9349f375a%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637598680703030828%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=%2Ffg7TXDA9%2F%2Fjin8T5f3V11fAv3PVvtDFluNHnhwyOGM%3Dreserved=0
> ___
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfxdata=04%7C01%7Calexander.deucher%40amd.com%7C096813db12f24172870508d9349f375a%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637598680703030828%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=%2Ffg7TXDA9%2F%2Fjin8T5f3V11fAv3PVvtDFluNHnhwyOGM%3Dreserved=0

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH v3 1/2] habanalabs: define uAPI to export FD for DMA-BUF

2021-06-21 Thread Oded Gabbay
On Mon, Jun 21, 2021 at 9:27 PM Daniel Vetter  wrote:
>
> On Mon, Jun 21, 2021 at 7:55 PM Jason Gunthorpe  wrote:
> > On Mon, Jun 21, 2021 at 07:26:14PM +0300, Oded Gabbay wrote:
> > > On Mon, Jun 21, 2021 at 5:12 PM Jason Gunthorpe  wrote:
> > > >
> > > > On Mon, Jun 21, 2021 at 03:02:10PM +0200, Greg KH wrote:
> > > > > On Mon, Jun 21, 2021 at 02:28:48PM +0200, Daniel Vetter wrote:
> > > >
> > > > > > Also I'm wondering which is the other driver that we share buffers
> > > > > > with. The gaudi stuff doesn't have real struct pages as backing
> > > > > > storage, it only fills out the dma_addr_t. That tends to blow up 
> > > > > > with
> > > > > > other drivers, and the only place where this is guaranteed to work 
> > > > > > is
> > > > > > if you have a dynamic importer which sets the allow_peer2peer flag.
> > > > > > Adding maintainers from other subsystems who might want to chime in
> > > > > > here. So even aside of the big question as-is this is broken.
> > > > >
> > > > > From what I can tell this driver is sending the buffers to other
> > > > > instances of the same hardware,
> > > >
> > > > A dmabuf is consumed by something else in the kernel calling
> > > > dma_buf_map_attachment() on the FD.
> > > >
> > > > What is the other side of this? I don't see any
> > > > dma_buf_map_attachment() calls in drivers/misc, or added in this patch
> > > > set.
> > >
> > > This patch-set is only to enable the support for the exporter side.
> > > The "other side" is any generic RDMA networking device that will want
> > > to perform p2p communication over PCIe with our GAUDI accelerator.
> > > An example is indeed the mlnx5 card which has already integrated
> > > support for being an "importer".
> >
> > It raises the question of how you are testing this if you aren't using
> > it with the only intree driver: mlx5.
>
> For p2p dma-buf there's also amdgpu as a possible in-tree candiate
> driver, that's why I added amdgpu folks. Otoh I'm not aware of AI+GPU
> combos being much in use, at least with upstream gpu drivers (nvidia
> blob is a different story ofc, but I don't care what they do in their
> own world).
> -Daniel
> --
We have/are doing three things:
1. I wrote a simple "importer" driver that emulates an RDMA driver. It
calls all the IB_UMEM_DMABUF functions, same as the mlnx5 driver does.
And instead of using h/w, it accesses the bar directly. We wrote
several tests that emulated the real application. i.e. asking the
habanalabs driver to create dma-buf object and export its FD back to
userspace. Then the userspace sends the FD to the "importer" driver,
which attaches to it, get the SG list and accesses the memory on the
GAUDI device. This gave me the confidence that how we integrated the
exporter is basically correct/working.

2. We are trying to do a POC with a MLNX card we have, WIP.

3. We are working with another 3rd party RDMA device that its driver
is now adding support for being an "importer". also WIP

In both points 2&3 We haven't yet reached the actual stage of checking
this feature.

Another thing I want to emphasize is that we are doing p2p only
through the export/import of the FD. We do *not* allow the user to
mmap the dma-buf as we do not support direct IO. So there is no access
to these pages through the userspace.

Thanks,
Oded
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH] drm/radeon: delete useless function return values & remove meaningless if(r) check code

2021-06-21 Thread Alex Deucher
Applied.  Thanks!

Alex

On Mon, Jun 21, 2021 at 9:15 AM Christian König
 wrote:
>
> Am 21.06.21 um 15:05 schrieb Bernard Zhao:
> > Function radeon_fence_driver_init always returns success,
> > the function type maybe coule be changed to void.
> > This patch first delete the check of the return
> > value of the function call radeon_fence_driver_init, then,
> > optimise the function declaration and function to void type.
> >
> > Signed-off-by: Bernard Zhao 
>
> Reviewed-by: Christian König 
>
> > ---
> >   drivers/gpu/drm/radeon/cik.c  | 4 +---
> >   drivers/gpu/drm/radeon/evergreen.c| 4 +---
> >   drivers/gpu/drm/radeon/ni.c   | 4 +---
> >   drivers/gpu/drm/radeon/r100.c | 4 +---
> >   drivers/gpu/drm/radeon/r300.c | 4 +---
> >   drivers/gpu/drm/radeon/r420.c | 5 +
> >   drivers/gpu/drm/radeon/r520.c | 4 +---
> >   drivers/gpu/drm/radeon/r600.c | 4 +---
> >   drivers/gpu/drm/radeon/radeon.h   | 2 +-
> >   drivers/gpu/drm/radeon/radeon_fence.c | 5 +
> >   drivers/gpu/drm/radeon/rs400.c| 4 +---
> >   drivers/gpu/drm/radeon/rs600.c| 4 +---
> >   drivers/gpu/drm/radeon/rs690.c| 4 +---
> >   drivers/gpu/drm/radeon/rv515.c| 4 +---
> >   drivers/gpu/drm/radeon/rv770.c| 4 +---
> >   drivers/gpu/drm/radeon/si.c   | 4 +---
> >   16 files changed, 16 insertions(+), 48 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
> > index 42a8afa839cb..f6cf0b8fdd83 100644
> > --- a/drivers/gpu/drm/radeon/cik.c
> > +++ b/drivers/gpu/drm/radeon/cik.c
> > @@ -8584,9 +8584,7 @@ int cik_init(struct radeon_device *rdev)
> >   radeon_get_clock_info(rdev->ddev);
> >
> >   /* Fence driver */
> > - r = radeon_fence_driver_init(rdev);
> > - if (r)
> > - return r;
> > + radeon_fence_driver_init(rdev);
> >
> >   /* initialize memory controller */
> >   r = cik_mc_init(rdev);
> > diff --git a/drivers/gpu/drm/radeon/evergreen.c 
> > b/drivers/gpu/drm/radeon/evergreen.c
> > index 8e9e88bf1f43..36a888e1b179 100644
> > --- a/drivers/gpu/drm/radeon/evergreen.c
> > +++ b/drivers/gpu/drm/radeon/evergreen.c
> > @@ -5208,9 +5208,7 @@ int evergreen_init(struct radeon_device *rdev)
> >   /* Initialize clocks */
> >   radeon_get_clock_info(rdev->ddev);
> >   /* Fence driver */
> > - r = radeon_fence_driver_init(rdev);
> > - if (r)
> > - return r;
> > + radeon_fence_driver_init(rdev);
> >   /* initialize AGP */
> >   if (rdev->flags & RADEON_IS_AGP) {
> >   r = radeon_agp_init(rdev);
> > diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
> > index ab7bd3080217..4a364ca7a1be 100644
> > --- a/drivers/gpu/drm/radeon/ni.c
> > +++ b/drivers/gpu/drm/radeon/ni.c
> > @@ -2375,9 +2375,7 @@ int cayman_init(struct radeon_device *rdev)
> >   /* Initialize clocks */
> >   radeon_get_clock_info(rdev->ddev);
> >   /* Fence driver */
> > - r = radeon_fence_driver_init(rdev);
> > - if (r)
> > - return r;
> > + radeon_fence_driver_init(rdev);
> >   /* initialize memory controller */
> >   r = evergreen_mc_init(rdev);
> >   if (r)
> > diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
> > index fcfcaec25a9e..aa6800b0e198 100644
> > --- a/drivers/gpu/drm/radeon/r100.c
> > +++ b/drivers/gpu/drm/radeon/r100.c
> > @@ -4056,9 +4056,7 @@ int r100_init(struct radeon_device *rdev)
> >   /* initialize VRAM */
> >   r100_mc_init(rdev);
> >   /* Fence driver */
> > - r = radeon_fence_driver_init(rdev);
> > - if (r)
> > - return r;
> > + radeon_fence_driver_init(rdev);
> >   /* Memory manager */
> >   r = radeon_bo_init(rdev);
> >   if (r)
> > diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
> > index 92643dfdd8a8..621ff174dff3 100644
> > --- a/drivers/gpu/drm/radeon/r300.c
> > +++ b/drivers/gpu/drm/radeon/r300.c
> > @@ -1549,9 +1549,7 @@ int r300_init(struct radeon_device *rdev)
> >   /* initialize memory controller */
> >   r300_mc_init(rdev);
> >   /* Fence driver */
> > - r = radeon_fence_driver_init(rdev);
> > - if (r)
> > - return r;
> > + radeon_fence_driver_init(rdev);
> >   /* Memory manager */
> >   r = radeon_bo_init(rdev);
> >   if (r)
> > diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c
> > index 1ed4407b91aa..7e6320e8c6a0 100644
> > --- a/drivers/gpu/drm/radeon/r420.c
> > +++ b/drivers/gpu/drm/radeon/r420.c
> > @@ -425,10 +425,7 @@ int r420_init(struct radeon_device *rdev)
> >   r300_mc_init(rdev);
> >   r420_debugfs(rdev);
> >   /* Fence driver */
> > - r = radeon_fence_driver_init(rdev);
> > - if (r) {
> > - return r;
> > - }
> > + radeon_fence_driver_init(rdev);
> >   /* Memory manager */
> >   r = radeon_bo_init(rdev);
> >   

Re: [PATCH 08/12] drm/amd/display: Fix edp_bootup_bl_level initialization issue

2021-06-21 Thread Harry Wentland



On 2021-06-18 3:07 p.m., Bindu Ramamurthy wrote:
> From: Logush Oliver 
> 
> [why]
> Updating the file to fix the missing line
> 
> Signed-off-by: Logush Oliver 
> Reviewed-by: Charlene Liu 
> Acked-by: Bindu Ramamurthy 
> ---
>  drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c 
> b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
> index 7d1c1b76d8d0..840d7aca17cf 100644
> --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
> +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
> @@ -2140,7 +2140,7 @@ static enum bp_result get_integrated_info_v2_1(
>   info_v2_1->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
>   info->edp1_info.edp_panel_bpc =
>   info_v2_1->edp1_info.edp_panel_bpc;
> - info->edp1_info.edp_bootup_bl_level =
> + info->edp1_info.edp_bootup_bl_level = 
> info_v2_1->edp1_info.edp_bootup_bl_level;
>  

This hints at a previous patch not building successfully. Please ensure
all patches in the series are building. It can be easily checked
with 'git rebase -i --exec make'.

Make sure this gets squashed with the faulty patch before merging.

Thanks,
Harry

>   info->edp2_info.edp_backlight_pwm_hz =
>   le16_to_cpu(info_v2_1->edp2_info.edp_backlight_pwm_hz);
> 

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH v3 1/2] habanalabs: define uAPI to export FD for DMA-BUF

2021-06-21 Thread Daniel Vetter
On Mon, Jun 21, 2021 at 7:55 PM Jason Gunthorpe  wrote:
> On Mon, Jun 21, 2021 at 07:26:14PM +0300, Oded Gabbay wrote:
> > On Mon, Jun 21, 2021 at 5:12 PM Jason Gunthorpe  wrote:
> > >
> > > On Mon, Jun 21, 2021 at 03:02:10PM +0200, Greg KH wrote:
> > > > On Mon, Jun 21, 2021 at 02:28:48PM +0200, Daniel Vetter wrote:
> > >
> > > > > Also I'm wondering which is the other driver that we share buffers
> > > > > with. The gaudi stuff doesn't have real struct pages as backing
> > > > > storage, it only fills out the dma_addr_t. That tends to blow up with
> > > > > other drivers, and the only place where this is guaranteed to work is
> > > > > if you have a dynamic importer which sets the allow_peer2peer flag.
> > > > > Adding maintainers from other subsystems who might want to chime in
> > > > > here. So even aside of the big question as-is this is broken.
> > > >
> > > > From what I can tell this driver is sending the buffers to other
> > > > instances of the same hardware,
> > >
> > > A dmabuf is consumed by something else in the kernel calling
> > > dma_buf_map_attachment() on the FD.
> > >
> > > What is the other side of this? I don't see any
> > > dma_buf_map_attachment() calls in drivers/misc, or added in this patch
> > > set.
> >
> > This patch-set is only to enable the support for the exporter side.
> > The "other side" is any generic RDMA networking device that will want
> > to perform p2p communication over PCIe with our GAUDI accelerator.
> > An example is indeed the mlnx5 card which has already integrated
> > support for being an "importer".
>
> It raises the question of how you are testing this if you aren't using
> it with the only intree driver: mlx5.

For p2p dma-buf there's also amdgpu as a possible in-tree candiate
driver, that's why I added amdgpu folks. Otoh I'm not aware of AI+GPU
combos being much in use, at least with upstream gpu drivers (nvidia
blob is a different story ofc, but I don't care what they do in their
own world).
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH v3 1/2] habanalabs: define uAPI to export FD for DMA-BUF

2021-06-21 Thread Jason Gunthorpe
On Mon, Jun 21, 2021 at 07:26:14PM +0300, Oded Gabbay wrote:
> On Mon, Jun 21, 2021 at 5:12 PM Jason Gunthorpe  wrote:
> >
> > On Mon, Jun 21, 2021 at 03:02:10PM +0200, Greg KH wrote:
> > > On Mon, Jun 21, 2021 at 02:28:48PM +0200, Daniel Vetter wrote:
> >
> > > > Also I'm wondering which is the other driver that we share buffers
> > > > with. The gaudi stuff doesn't have real struct pages as backing
> > > > storage, it only fills out the dma_addr_t. That tends to blow up with
> > > > other drivers, and the only place where this is guaranteed to work is
> > > > if you have a dynamic importer which sets the allow_peer2peer flag.
> > > > Adding maintainers from other subsystems who might want to chime in
> > > > here. So even aside of the big question as-is this is broken.
> > >
> > > From what I can tell this driver is sending the buffers to other
> > > instances of the same hardware,
> >
> > A dmabuf is consumed by something else in the kernel calling
> > dma_buf_map_attachment() on the FD.
> >
> > What is the other side of this? I don't see any
> > dma_buf_map_attachment() calls in drivers/misc, or added in this patch
> > set.
> 
> This patch-set is only to enable the support for the exporter side.
> The "other side" is any generic RDMA networking device that will want
> to perform p2p communication over PCIe with our GAUDI accelerator.
> An example is indeed the mlnx5 card which has already integrated
> support for being an "importer".

It raises the question of how you are testing this if you aren't using
it with the only intree driver: mlx5.

Jason
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH v3 1/2] habanalabs: define uAPI to export FD for DMA-BUF

2021-06-21 Thread Oded Gabbay
On Mon, Jun 21, 2021 at 5:12 PM Jason Gunthorpe  wrote:
>
> On Mon, Jun 21, 2021 at 03:02:10PM +0200, Greg KH wrote:
> > On Mon, Jun 21, 2021 at 02:28:48PM +0200, Daniel Vetter wrote:
>
> > > Also I'm wondering which is the other driver that we share buffers
> > > with. The gaudi stuff doesn't have real struct pages as backing
> > > storage, it only fills out the dma_addr_t. That tends to blow up with
> > > other drivers, and the only place where this is guaranteed to work is
> > > if you have a dynamic importer which sets the allow_peer2peer flag.
> > > Adding maintainers from other subsystems who might want to chime in
> > > here. So even aside of the big question as-is this is broken.
> >
> > From what I can tell this driver is sending the buffers to other
> > instances of the same hardware,
>
> A dmabuf is consumed by something else in the kernel calling
> dma_buf_map_attachment() on the FD.
>
> What is the other side of this? I don't see any
> dma_buf_map_attachment() calls in drivers/misc, or added in this patch
> set.

This patch-set is only to enable the support for the exporter side.
The "other side" is any generic RDMA networking device that will want
to perform p2p communication over PCIe with our GAUDI accelerator.
An example is indeed the mlnx5 card which has already integrated
support for being an "importer".

This is *not* used for communication with another GAUDI device. If I
want to communicate with another GAUDI device, our userspace
communications library will use our internal network links, without
any need for dma-buf.

Oded

>
> AFAIK the only viable in-tree other side is in mlx5 (look in
> umem_dmabuf.c)
>
> Though as we already talked habana has their own networking (out of
> tree, presumably) so I suspect this is really to support some out of
> tree stuff??
>
> Jason
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [kbuild-all] Re: [PATCH] drm/radeon: Fix NULL dereference when updating memory stats

2021-06-21 Thread Philip Li
On Mon, Jun 21, 2021 at 10:41:57PM +0800, kernel test robot wrote:
> Hi Mikel,
> 
> Thank you for the patch! Yet something to improve:
> 
> [auto build test ERROR on next-20210618]
> [cannot apply to linus/master v5.13-rc7 v5.13-rc6 v5.13-rc5 v5.13-rc7]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch]
> 
> url:
> https://github.com/0day-ci/linux/commits/Mikel-Rychliski/drm-radeon-Fix-NULL-dereference-when-updating-memory-stats/20210621-091140
> base:e71e3a48a7e89fa71fb70bf4602367528864d2ff
> config: mips-allyesconfig (attached as .config)
> compiler: mips-linux-gcc (GCC) 9.3.0
> reproduce (this is a W=1 build):
> wget 
> https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
> ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # 
> https://github.com/0day-ci/linux/commit/e5ec8682645a1ee2553fcb073d000802c11d2cb5
> git remote add linux-review https://github.com/0day-ci/linux
> git fetch --no-tags linux-review 
> Mikel-Rychliski/drm-radeon-Fix-NULL-dereference-when-updating-memory-stats/20210621-091140
> git checkout e5ec8682645a1ee2553fcb073d000802c11d2cb5
> # save the attached .config to linux build tree
> COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross 
> ARCH=mips 
> 
> If you fix the issue, kindly add following tag as appropriate
> Reported-by: kernel test robot 
> 
> All errors (new ones prefixed by >>):
Sorry for the broken report, kindly ignore this, we will fix
this asap.

> 
> >> make[2]: *** No rule to make target 
> >> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/accessibility/speakup/speakup_decpc.ko',
> >>  needed by '__modinst'.
> >> make[2]: *** No rule to make target 
> >> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/base/test/test_async_driver_probe.ko',
> >>  needed by '__modinst'.
> >> make[2]: *** No rule to make target 
> >> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/i2c/i2c-stub.ko',
> >>  needed by '__modinst'.
> >> make[2]: *** No rule to make target 
> >> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_nandbiterrs.ko',
> >>  needed by '__modinst'.
> >> make[2]: *** No rule to make target 
> >> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_nandecctest.ko',
> >>  needed by '__modinst'.
> >> make[2]: *** No rule to make target 
> >> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_oobtest.ko',
> >>  needed by '__modinst'.
> >> make[2]: *** No rule to make target 
> >> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_pagetest.ko',
> >>  needed by '__modinst'.
> >> make[2]: *** No rule to make target 
> >> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_readtest.ko',
> >>  needed by '__modinst'.
> >> make[2]: *** No rule to make target 
> >> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_speedtest.ko',
> >>  needed by '__modinst'.
> >> make[2]: *** No rule to make target 
> >> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_stresstest.ko',
> >>  needed by '__modinst'.
> >> make[2]: *** No rule to make target 
> >> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_subpagetest.ko',
> >>  needed by '__modinst'.
> >> make[2]: *** No rule to make target 
> >> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_torturetest.ko',
> >>  needed by '__modinst'.
> &

Re: [PATCH V3 1/7] drm/amdgpu: correct tcp harvest setting

2021-06-21 Thread Lazar, Lijo

One minor comment below, apart from that the series looks good.

Reviewed-by: Lijo Lazar 

On 6/21/2021 12:30 PM, Evan Quan wrote:

Add missing settings for SQC bits. And correct some confusing logics
around active wgp bitmap calculation.

Change-Id: If4992e175fd61d5609b00328cbe21f487517d039
Signed-off-by: Evan Quan 
---
V1->V2:
   - restore correct tcp_harvest setting for NV10 and NV12
   - move asic type guard upper layer for better readability
---
  drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 103 ++---
  1 file changed, 57 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c 
b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 15ae9e33b925..384b95fbad8b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -5090,47 +5090,50 @@ static void gfx_v10_0_tcp_harvest(struct amdgpu_device 
*adev)
4 + /* RMI */
1); /* SQG */
  
-	if (adev->asic_type == CHIP_NAVI10 ||

-   adev->asic_type == CHIP_NAVI14 ||
-   adev->asic_type == CHIP_NAVI12) {
-   mutex_lock(>grbm_idx_mutex);
-   for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
-   for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
-   gfx_v10_0_select_se_sh(adev, i, j, 0x);
-   wgp_active_bitmap = 
gfx_v10_0_get_wgp_active_bitmap_per_sh(adev);
-   /*
-* Set corresponding TCP bits for the inactive 
WGPs in
-* GCRD_SA_TARGETS_DISABLE
-*/
-   gcrd_targets_disable_tcp = 0;
-   /* Set TCP & SQC bits in 
UTCL1_UTCL0_INVREQ_DISABLE */
-   utcl_invreq_disable = 0;
-
-   for (k = 0; k < max_wgp_per_sh; k++) {
-   if (!(wgp_active_bitmap & (1 << k))) {
-   gcrd_targets_disable_tcp |= 3 
<< (2 * k);
-   utcl_invreq_disable |= (3 << (2 
* k)) |
-   (3 << (2 * 
(max_wgp_per_sh + k)));
-   }
+   mutex_lock(>grbm_idx_mutex);
+   for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
+   for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
+   gfx_v10_0_select_se_sh(adev, i, j, 0x);
+   wgp_active_bitmap = 
gfx_v10_0_get_wgp_active_bitmap_per_sh(adev);
+   /*
+* Set corresponding TCP bits for the inactive WGPs in
+* GCRD_SA_TARGETS_DISABLE
+*/
+   gcrd_targets_disable_tcp = 0;
+   /* Set TCP & SQC bits in UTCL1_UTCL0_INVREQ_DISABLE */
+   utcl_invreq_disable = 0;
+
+   for (k = 0; k < max_wgp_per_sh; k++) {
+   if (!(wgp_active_bitmap & (1 << k))) {
+   gcrd_targets_disable_tcp |= 3 << (2 * 
k);
+   gcrd_targets_disable_tcp |= 1 << (k + 
(max_wgp_per_sh * 2));
+   utcl_invreq_disable |= (3 << (2 * k)) |
+   (3 << (2 * (max_wgp_per_sh + 
k)));
}
-
-   tmp = RREG32_SOC15(GC, 0, 
mmUTCL1_UTCL0_INVREQ_DISABLE);
-   /* only override TCP & SQC bits */
-   tmp &= 0x << (4 * max_wgp_per_sh);
-   tmp |= (utcl_invreq_disable & 
utcl_invreq_disable_mask);
-   WREG32_SOC15(GC, 0, 
mmUTCL1_UTCL0_INVREQ_DISABLE, tmp);
-
-   tmp = RREG32_SOC15(GC, 0, 
mmGCRD_SA_TARGETS_DISABLE);
-   /* only override TCP bits */
-   tmp &= 0x << (2 * max_wgp_per_sh);
-   tmp |= (gcrd_targets_disable_tcp & 
gcrd_targets_disable_mask);
-   WREG32_SOC15(GC, 0, mmGCRD_SA_TARGETS_DISABLE, 
tmp);
}
-   }
  
-		gfx_v10_0_select_se_sh(adev, 0x, 0x, 0x);

-   mutex_unlock(>grbm_idx_mutex);
+   tmp = RREG32_SOC15(GC, 0, mmUTCL1_UTCL0_INVREQ_DISABLE);
+   /* only override TCP & SQC bits */
+   if (adev->asic_type == CHIP_NAVI14)
+   tmp &= 0xff00;
+   else
+   tmp &=0xfff0;


For the disable field mask calculation (which is the value that is 
applied finally), there is no 

Re: [PATCH 1/3] drm/nouveau: wait for moving fence after pinning

2021-06-21 Thread Daniel Vetter
On Mon, Jun 21, 2021 at 5:49 PM Christian König
 wrote:
>
> Am 21.06.21 um 16:54 schrieb Daniel Vetter:
> > On Mon, Jun 21, 2021 at 03:03:26PM +0200, Christian König wrote:
> >> We actually need to wait for the moving fence after pinning
> >> the BO to make sure that the pin is completed.
> >>
> >> Signed-off-by: Christian König 
> >> CC: sta...@kernel.org
> >> ---
> >>   drivers/gpu/drm/nouveau/nouveau_prime.c | 8 +++-
> >>   1 file changed, 7 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c 
> >> b/drivers/gpu/drm/nouveau/nouveau_prime.c
> >> index 347488685f74..591738545eba 100644
> >> --- a/drivers/gpu/drm/nouveau/nouveau_prime.c
> >> +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c
> >> @@ -93,7 +93,13 @@ int nouveau_gem_prime_pin(struct drm_gem_object *obj)
> >>  if (ret)
> >>  return -EINVAL;
> >>
> >> -return 0;
> >> +if (nvbo->bo.moving) {
> > Don't we need to hold the dma_resv to read this? We can grab a reference
> > and then unlock, but I think just unlocked wait can go boom pretty easily
> > (since we don't hold a reference or lock so someone else can jump in and
> > free the moving fence).
>
> The moving fence is only modified while the BO is moved and since we
> have just successfully pinned it

Yeah  ... so probably correct, but really tricky. Just wrapping a
ttm_bo_reserve/unreserve around the code you add should be enough and
get the job done?

> But in general I agree that it would be better to avoid this. I just
> didn't wanted to open a bigger can of worms by changing nouveau so much.

Yeah, but I'm kinda thinking of some helpers to wait for the move
fence (so that later on we can switch from having the exclusive fence
to the move fence do that, maybe). And then locking checks in there
would be nice.

Also avoids the case of explaining why lockless here is fine, but
lockless wait for the exclusive fence in e.g. a dynami dma-buf
importer is very much not fine at all. Just all around less trouble.
-Daniel

>
> Christian.
>
> > -Daniel
> >
> >> +ret = dma_fence_wait(nvbo->bo.moving, true);
> >> +if (ret)
> >> +nouveau_bo_unpin(nvbo);
> >> +}
> >> +
> >> +return ret;
> >>   }
> >>
> >>   void nouveau_gem_prime_unpin(struct drm_gem_object *obj)
> >> --
> >> 2.25.1
> >>
>


-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH 1/3] drm/nouveau: wait for moving fence after pinning

2021-06-21 Thread Christian König

Am 21.06.21 um 16:54 schrieb Daniel Vetter:

On Mon, Jun 21, 2021 at 03:03:26PM +0200, Christian König wrote:

We actually need to wait for the moving fence after pinning
the BO to make sure that the pin is completed.

Signed-off-by: Christian König 
CC: sta...@kernel.org
---
  drivers/gpu/drm/nouveau/nouveau_prime.c | 8 +++-
  1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c 
b/drivers/gpu/drm/nouveau/nouveau_prime.c
index 347488685f74..591738545eba 100644
--- a/drivers/gpu/drm/nouveau/nouveau_prime.c
+++ b/drivers/gpu/drm/nouveau/nouveau_prime.c
@@ -93,7 +93,13 @@ int nouveau_gem_prime_pin(struct drm_gem_object *obj)
if (ret)
return -EINVAL;
  
-	return 0;

+   if (nvbo->bo.moving) {

Don't we need to hold the dma_resv to read this? We can grab a reference
and then unlock, but I think just unlocked wait can go boom pretty easily
(since we don't hold a reference or lock so someone else can jump in and
free the moving fence).


The moving fence is only modified while the BO is moved and since we 
have just successfully pinned it


But in general I agree that it would be better to avoid this. I just 
didn't wanted to open a bigger can of worms by changing nouveau so much.


Christian.


-Daniel


+   ret = dma_fence_wait(nvbo->bo.moving, true);
+   if (ret)
+   nouveau_bo_unpin(nvbo);
+   }
+
+   return ret;
  }
  
  void nouveau_gem_prime_unpin(struct drm_gem_object *obj)

--
2.25.1



___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH 1/1] drm/amdgpu: add helper function for vm pasid

2021-06-21 Thread Das, Nirmoy


On 6/21/2021 1:35 PM, Christian König wrote:

Am 21.06.21 um 13:27 schrieb Das, Nirmoy:


On 6/21/2021 1:18 PM, Christian König wrote:

Am 21.06.21 um 13:10 schrieb Das, Nirmoy:


On 6/21/2021 12:59 PM, Christian König wrote:

Am 21.06.21 um 12:56 schrieb Das, Nirmoy:


On 6/21/2021 12:26 PM, Christian König wrote:
Well you completely break the handling in 
amdgpu_vm_handle_fault() with this.



I see one issue with:  if (!vm || (vm && vm->root.bo != root)) . 
I will split it and resend.


Am I missing something else ?


The problem is you drop and re-take the lock now at the wrong time.



I see the problem.



I don't think what you try to do here is possible at all.



Does it makes sense to resend without amdgpu_vm_handle_fault() 
changes ?


Some other changes don't make sense to me as well.

For example:

pasid = amdgpu_pasid_alloc(16);

Why do you want to allocate a hard coded pasid number here?



This is from  original amdgpu_driver_open_kms(). We are allocating a 
pasid number and passing that to


amdgpu_vm_init(). I wanted to move that to vmcode with this patch.


That doesn't make sense.

The pasid is a hardware identify which is unrelated to the VM in 
general and might at some point passed in from external.




Ok, makes sense. I will remove that part then.


Nirmoy


Please keep that as parameter to the VM code if possible.

Christian.




Regards,

Nirmoy




Christian.






Christian.




Regards,

Nirmoy





Christian.

Am 21.06.21 um 11:47 schrieb Das, Nirmoy:

ping.

On 6/17/2021 3:03 PM, Nirmoy Das wrote:

Cleanup code related to vm pasid by adding helper function.
This reduces lots code duplication.

Signed-off-by: Nirmoy Das 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |  17 +--
  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c  | 176 


  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h  |   2 +-
  3 files changed, 96 insertions(+), 99 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c

index cbb932f97355..27851fb0e25b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -1149,7 +1149,7 @@ int amdgpu_driver_open_kms(struct 
drm_device *dev, struct drm_file *file_priv)

  {
  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_fpriv *fpriv;
-    int r, pasid;
+    int r;
    /* Ensure IB tests are run on ring */
flush_delayed_work(>delayed_init_work);
@@ -1172,15 +1172,9 @@ int amdgpu_driver_open_kms(struct 
drm_device *dev, struct drm_file *file_priv)

  goto out_suspend;
  }
  -    pasid = amdgpu_pasid_alloc(16);
-    if (pasid < 0) {
-    dev_warn(adev->dev, "No more PASIDs available!");
-    pasid = 0;
-    }
-
-    r = amdgpu_vm_init(adev, >vm, pasid);
+    r = amdgpu_vm_init(adev, >vm);
  if (r)
-    goto error_pasid;
+    goto free_fpriv;
    fpriv->prt_va = amdgpu_vm_bo_add(adev, >vm, NULL);
  if (!fpriv->prt_va) {
@@ -1208,10 +1202,7 @@ int amdgpu_driver_open_kms(struct 
drm_device *dev, struct drm_file *file_priv)

  error_vm:
  amdgpu_vm_fini(adev, >vm);
  -error_pasid:
-    if (pasid)
-    amdgpu_pasid_free(pasid);
-
+free_fpriv:
  kfree(fpriv);
    out_suspend:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

index 63975bda8e76..562c2c48a3a3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -87,6 +87,69 @@ struct amdgpu_prt_cb {
  struct dma_fence_cb cb;
  };
  +static int amdgpu_vm_pasid_alloc(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm, unsigned int pasid)
+{
+    unsigned long flags;
+    int r;
+
+    if (!pasid)
+    return 0;
+
+ spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    r = idr_alloc(>vm_manager.pasid_idr, vm, pasid, 
pasid + 1,

+  GFP_ATOMIC);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+    if (r < 0)
+    return r;
+
+    vm->pasid = pasid;
+    return 0;
+}
+static void amdgpu_vm_pasid_remove_id(struct amdgpu_device 
*adev,

+  unsigned int pasid)
+{
+    unsigned long flags;
+
+    if (!pasid)
+    return;
+
+ spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+ idr_remove(>vm_manager.pasid_idr, pasid);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+
+}
+
+static void amdgpu_vm_pasid_remove(struct amdgpu_device *adev,
+   struct amdgpu_vm *vm)
+{
+    amdgpu_vm_pasid_remove_id(adev, vm->pasid);
+    vm->pasid = 0;
+}
+
+static void amdgpu_vm_pasid_free(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm)
+{
+    if (!vm->pasid)
+    return;
+
+    amdgpu_pasid_free(vm->pasid);
+    amdgpu_vm_pasid_remove(adev, vm);
+}
+
+static struct amdgpu_vm *amdgpu_vm_pasid_find(struct 
amdgpu_device *adev,

+  unsigned int pasid)
+{
+    struct amdgpu_vm *vm;
+    unsigned long flags;
+
+ 

Re: [PATCH 1/1] drm/amdgpu: add helper function for vm pasid

2021-06-21 Thread Christian König

Am 21.06.21 um 13:27 schrieb Das, Nirmoy:


On 6/21/2021 1:18 PM, Christian König wrote:

Am 21.06.21 um 13:10 schrieb Das, Nirmoy:


On 6/21/2021 12:59 PM, Christian König wrote:

Am 21.06.21 um 12:56 schrieb Das, Nirmoy:


On 6/21/2021 12:26 PM, Christian König wrote:
Well you completely break the handling in 
amdgpu_vm_handle_fault() with this.



I see one issue with:  if (!vm || (vm && vm->root.bo != root)) . I 
will split it and resend.


Am I missing something else ?


The problem is you drop and re-take the lock now at the wrong time.



I see the problem.



I don't think what you try to do here is possible at all.



Does it makes sense to resend without amdgpu_vm_handle_fault() 
changes ?


Some other changes don't make sense to me as well.

For example:

pasid = amdgpu_pasid_alloc(16);

Why do you want to allocate a hard coded pasid number here?



This is from  original amdgpu_driver_open_kms(). We are allocating a 
pasid number and passing that to


amdgpu_vm_init(). I wanted to move that to vmcode with this patch.


That doesn't make sense.

The pasid is a hardware identify which is unrelated to the VM in general 
and might at some point passed in from external.


Please keep that as parameter to the VM code if possible.

Christian.




Regards,

Nirmoy




Christian.






Christian.




Regards,

Nirmoy





Christian.

Am 21.06.21 um 11:47 schrieb Das, Nirmoy:

ping.

On 6/17/2021 3:03 PM, Nirmoy Das wrote:

Cleanup code related to vm pasid by adding helper function.
This reduces lots code duplication.

Signed-off-by: Nirmoy Das 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |  17 +--
  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c  | 176 


  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h  |   2 +-
  3 files changed, 96 insertions(+), 99 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c

index cbb932f97355..27851fb0e25b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -1149,7 +1149,7 @@ int amdgpu_driver_open_kms(struct 
drm_device *dev, struct drm_file *file_priv)

  {
  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_fpriv *fpriv;
-    int r, pasid;
+    int r;
    /* Ensure IB tests are run on ring */
flush_delayed_work(>delayed_init_work);
@@ -1172,15 +1172,9 @@ int amdgpu_driver_open_kms(struct 
drm_device *dev, struct drm_file *file_priv)

  goto out_suspend;
  }
  -    pasid = amdgpu_pasid_alloc(16);
-    if (pasid < 0) {
-    dev_warn(adev->dev, "No more PASIDs available!");
-    pasid = 0;
-    }
-
-    r = amdgpu_vm_init(adev, >vm, pasid);
+    r = amdgpu_vm_init(adev, >vm);
  if (r)
-    goto error_pasid;
+    goto free_fpriv;
    fpriv->prt_va = amdgpu_vm_bo_add(adev, >vm, NULL);
  if (!fpriv->prt_va) {
@@ -1208,10 +1202,7 @@ int amdgpu_driver_open_kms(struct 
drm_device *dev, struct drm_file *file_priv)

  error_vm:
  amdgpu_vm_fini(adev, >vm);
  -error_pasid:
-    if (pasid)
-    amdgpu_pasid_free(pasid);
-
+free_fpriv:
  kfree(fpriv);
    out_suspend:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

index 63975bda8e76..562c2c48a3a3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -87,6 +87,69 @@ struct amdgpu_prt_cb {
  struct dma_fence_cb cb;
  };
  +static int amdgpu_vm_pasid_alloc(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm, unsigned int pasid)
+{
+    unsigned long flags;
+    int r;
+
+    if (!pasid)
+    return 0;
+
+ spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    r = idr_alloc(>vm_manager.pasid_idr, vm, pasid, 
pasid + 1,

+  GFP_ATOMIC);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+    if (r < 0)
+    return r;
+
+    vm->pasid = pasid;
+    return 0;
+}
+static void amdgpu_vm_pasid_remove_id(struct amdgpu_device *adev,
+  unsigned int pasid)
+{
+    unsigned long flags;
+
+    if (!pasid)
+    return;
+
+ spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    idr_remove(>vm_manager.pasid_idr, pasid);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+
+}
+
+static void amdgpu_vm_pasid_remove(struct amdgpu_device *adev,
+   struct amdgpu_vm *vm)
+{
+    amdgpu_vm_pasid_remove_id(adev, vm->pasid);
+    vm->pasid = 0;
+}
+
+static void amdgpu_vm_pasid_free(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm)
+{
+    if (!vm->pasid)
+    return;
+
+    amdgpu_pasid_free(vm->pasid);
+    amdgpu_vm_pasid_remove(adev, vm);
+}
+
+static struct amdgpu_vm *amdgpu_vm_pasid_find(struct 
amdgpu_device *adev,

+  unsigned int pasid)
+{
+    struct amdgpu_vm *vm;
+    unsigned long flags;
+
+ spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    vm = idr_find(>vm_manager.pasid_idr, pasid);
+ 

Re: [PATCH 1/1] drm/amdgpu: add helper function for vm pasid

2021-06-21 Thread Das, Nirmoy


On 6/21/2021 1:18 PM, Christian König wrote:

Am 21.06.21 um 13:10 schrieb Das, Nirmoy:


On 6/21/2021 12:59 PM, Christian König wrote:

Am 21.06.21 um 12:56 schrieb Das, Nirmoy:


On 6/21/2021 12:26 PM, Christian König wrote:
Well you completely break the handling in amdgpu_vm_handle_fault() 
with this.



I see one issue with:  if (!vm || (vm && vm->root.bo != root)) . I 
will split it and resend.


Am I missing something else ?


The problem is you drop and re-take the lock now at the wrong time.



I see the problem.



I don't think what you try to do here is possible at all.



Does it makes sense to resend without amdgpu_vm_handle_fault() changes ?


Some other changes don't make sense to me as well.

For example:

pasid = amdgpu_pasid_alloc(16);

Why do you want to allocate a hard coded pasid number here?



This is from  original amdgpu_driver_open_kms(). We are allocating a 
pasid number and passing that to


amdgpu_vm_init(). I wanted to move that to vmcode with this patch.


Regards,

Nirmoy




Christian.






Christian.




Regards,

Nirmoy





Christian.

Am 21.06.21 um 11:47 schrieb Das, Nirmoy:

ping.

On 6/17/2021 3:03 PM, Nirmoy Das wrote:

Cleanup code related to vm pasid by adding helper function.
This reduces lots code duplication.

Signed-off-by: Nirmoy Das 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |  17 +--
  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c  | 176 


  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h  |   2 +-
  3 files changed, 96 insertions(+), 99 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c

index cbb932f97355..27851fb0e25b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -1149,7 +1149,7 @@ int amdgpu_driver_open_kms(struct 
drm_device *dev, struct drm_file *file_priv)

  {
  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_fpriv *fpriv;
-    int r, pasid;
+    int r;
    /* Ensure IB tests are run on ring */
flush_delayed_work(>delayed_init_work);
@@ -1172,15 +1172,9 @@ int amdgpu_driver_open_kms(struct 
drm_device *dev, struct drm_file *file_priv)

  goto out_suspend;
  }
  -    pasid = amdgpu_pasid_alloc(16);
-    if (pasid < 0) {
-    dev_warn(adev->dev, "No more PASIDs available!");
-    pasid = 0;
-    }
-
-    r = amdgpu_vm_init(adev, >vm, pasid);
+    r = amdgpu_vm_init(adev, >vm);
  if (r)
-    goto error_pasid;
+    goto free_fpriv;
    fpriv->prt_va = amdgpu_vm_bo_add(adev, >vm, NULL);
  if (!fpriv->prt_va) {
@@ -1208,10 +1202,7 @@ int amdgpu_driver_open_kms(struct 
drm_device *dev, struct drm_file *file_priv)

  error_vm:
  amdgpu_vm_fini(adev, >vm);
  -error_pasid:
-    if (pasid)
-    amdgpu_pasid_free(pasid);
-
+free_fpriv:
  kfree(fpriv);
    out_suspend:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

index 63975bda8e76..562c2c48a3a3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -87,6 +87,69 @@ struct amdgpu_prt_cb {
  struct dma_fence_cb cb;
  };
  +static int amdgpu_vm_pasid_alloc(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm, unsigned int pasid)
+{
+    unsigned long flags;
+    int r;
+
+    if (!pasid)
+    return 0;
+
+ spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    r = idr_alloc(>vm_manager.pasid_idr, vm, pasid, pasid 
+ 1,

+  GFP_ATOMIC);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+    if (r < 0)
+    return r;
+
+    vm->pasid = pasid;
+    return 0;
+}
+static void amdgpu_vm_pasid_remove_id(struct amdgpu_device *adev,
+  unsigned int pasid)
+{
+    unsigned long flags;
+
+    if (!pasid)
+    return;
+
+ spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    idr_remove(>vm_manager.pasid_idr, pasid);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+
+}
+
+static void amdgpu_vm_pasid_remove(struct amdgpu_device *adev,
+   struct amdgpu_vm *vm)
+{
+    amdgpu_vm_pasid_remove_id(adev, vm->pasid);
+    vm->pasid = 0;
+}
+
+static void amdgpu_vm_pasid_free(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm)
+{
+    if (!vm->pasid)
+    return;
+
+    amdgpu_pasid_free(vm->pasid);
+    amdgpu_vm_pasid_remove(adev, vm);
+}
+
+static struct amdgpu_vm *amdgpu_vm_pasid_find(struct 
amdgpu_device *adev,

+  unsigned int pasid)
+{
+    struct amdgpu_vm *vm;
+    unsigned long flags;
+
+ spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    vm = idr_find(>vm_manager.pasid_idr, pasid);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+
+    return vm;
+}
+
  /*
   * vm eviction_lock can be taken in MMU notifiers. Make sure 
no reclaim-FS
   * happens while holding this lock anywhere to prevent 
deadlocks when
@@ -2859,17 +2922,17 @@ long amdgpu_vm_wait_idle(struct 
amdgpu_vm *vm, 

Re: [PATCH v3 1/2] habanalabs: define uAPI to export FD for DMA-BUF

2021-06-21 Thread Jason Gunthorpe
On Mon, Jun 21, 2021 at 04:20:35PM +0200, Daniel Vetter wrote:

> Also unless we're actually doing this properly there's zero incentive for
> me to review the kernel code and check whether it follows the rules
> correctly, so you have excellent chances that you just break the rules.
> And dma_buf/fence are tricky enough that you pretty much guaranteed to
> break the rules if you're not involved in the discussions. Just now we
> have a big one where everyone involved (who's been doing this for 10+
> years all at least) realizes we've fucked up big time.

This is where I come from on dmabuf, it is fiendishly
complicated. Don't use it unless you absoultely have to, are in DRM,
and have people like Daniel helping to make sure you use it right.

It's whole premise and design is compromised by specialty historical
implementation choices on the GPU side.

Jason
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH 1/1] drm/amdgpu: add helper function for vm pasid

2021-06-21 Thread Das, Nirmoy


On 6/21/2021 12:59 PM, Christian König wrote:

Am 21.06.21 um 12:56 schrieb Das, Nirmoy:


On 6/21/2021 12:26 PM, Christian König wrote:
Well you completely break the handling in amdgpu_vm_handle_fault() 
with this.



I see one issue with:  if (!vm || (vm && vm->root.bo != root)) . I 
will split it and resend.


Am I missing something else ?


The problem is you drop and re-take the lock now at the wrong time.



I see the problem.



I don't think what you try to do here is possible at all.



Does it makes sense to resend without amdgpu_vm_handle_fault() changes ?



Christian.




Regards,

Nirmoy





Christian.

Am 21.06.21 um 11:47 schrieb Das, Nirmoy:

ping.

On 6/17/2021 3:03 PM, Nirmoy Das wrote:

Cleanup code related to vm pasid by adding helper function.
This reduces lots code duplication.

Signed-off-by: Nirmoy Das 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |  17 +--
  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c  | 176 


  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h  |   2 +-
  3 files changed, 96 insertions(+), 99 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c

index cbb932f97355..27851fb0e25b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -1149,7 +1149,7 @@ int amdgpu_driver_open_kms(struct drm_device 
*dev, struct drm_file *file_priv)

  {
  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_fpriv *fpriv;
-    int r, pasid;
+    int r;
    /* Ensure IB tests are run on ring */
  flush_delayed_work(>delayed_init_work);
@@ -1172,15 +1172,9 @@ int amdgpu_driver_open_kms(struct 
drm_device *dev, struct drm_file *file_priv)

  goto out_suspend;
  }
  -    pasid = amdgpu_pasid_alloc(16);
-    if (pasid < 0) {
-    dev_warn(adev->dev, "No more PASIDs available!");
-    pasid = 0;
-    }
-
-    r = amdgpu_vm_init(adev, >vm, pasid);
+    r = amdgpu_vm_init(adev, >vm);
  if (r)
-    goto error_pasid;
+    goto free_fpriv;
    fpriv->prt_va = amdgpu_vm_bo_add(adev, >vm, NULL);
  if (!fpriv->prt_va) {
@@ -1208,10 +1202,7 @@ int amdgpu_driver_open_kms(struct 
drm_device *dev, struct drm_file *file_priv)

  error_vm:
  amdgpu_vm_fini(adev, >vm);
  -error_pasid:
-    if (pasid)
-    amdgpu_pasid_free(pasid);
-
+free_fpriv:
  kfree(fpriv);
    out_suspend:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

index 63975bda8e76..562c2c48a3a3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -87,6 +87,69 @@ struct amdgpu_prt_cb {
  struct dma_fence_cb cb;
  };
  +static int amdgpu_vm_pasid_alloc(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm, unsigned int pasid)
+{
+    unsigned long flags;
+    int r;
+
+    if (!pasid)
+    return 0;
+
+ spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    r = idr_alloc(>vm_manager.pasid_idr, vm, pasid, pasid + 1,
+  GFP_ATOMIC);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+    if (r < 0)
+    return r;
+
+    vm->pasid = pasid;
+    return 0;
+}
+static void amdgpu_vm_pasid_remove_id(struct amdgpu_device *adev,
+  unsigned int pasid)
+{
+    unsigned long flags;
+
+    if (!pasid)
+    return;
+
+ spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    idr_remove(>vm_manager.pasid_idr, pasid);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+
+}
+
+static void amdgpu_vm_pasid_remove(struct amdgpu_device *adev,
+   struct amdgpu_vm *vm)
+{
+    amdgpu_vm_pasid_remove_id(adev, vm->pasid);
+    vm->pasid = 0;
+}
+
+static void amdgpu_vm_pasid_free(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm)
+{
+    if (!vm->pasid)
+    return;
+
+    amdgpu_pasid_free(vm->pasid);
+    amdgpu_vm_pasid_remove(adev, vm);
+}
+
+static struct amdgpu_vm *amdgpu_vm_pasid_find(struct 
amdgpu_device *adev,

+  unsigned int pasid)
+{
+    struct amdgpu_vm *vm;
+    unsigned long flags;
+
+ spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    vm = idr_find(>vm_manager.pasid_idr, pasid);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+
+    return vm;
+}
+
  /*
   * vm eviction_lock can be taken in MMU notifiers. Make sure no 
reclaim-FS
   * happens while holding this lock anywhere to prevent deadlocks 
when
@@ -2859,17 +2922,17 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm 
*vm, long timeout)

   *
   * @adev: amdgpu_device pointer
   * @vm: requested vm
- * @pasid: Process address space identifier
   *
   * Init @vm fields.
   *
   * Returns:
   * 0 for success, error for failure.
   */
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm 
*vm, u32 pasid)

+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
  {
  struct amdgpu_bo *root_bo;
  struct amdgpu_bo_vm *root;
+    unsigned int 

Re: [PATCH 1/1] drm/amdgpu: add helper function for vm pasid

2021-06-21 Thread Christian König

Am 21.06.21 um 12:56 schrieb Das, Nirmoy:


On 6/21/2021 12:26 PM, Christian König wrote:
Well you completely break the handling in amdgpu_vm_handle_fault() 
with this.



I see one issue with:  if (!vm || (vm && vm->root.bo != root)) . I 
will split it and resend.


Am I missing something else ?


The problem is you drop and re-take the lock now at the wrong time.

I don't think what you try to do here is possible at all.

Christian.




Regards,

Nirmoy





Christian.

Am 21.06.21 um 11:47 schrieb Das, Nirmoy:

ping.

On 6/17/2021 3:03 PM, Nirmoy Das wrote:

Cleanup code related to vm pasid by adding helper function.
This reduces lots code duplication.

Signed-off-by: Nirmoy Das 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |  17 +--
  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c  | 176 


  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h  |   2 +-
  3 files changed, 96 insertions(+), 99 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c

index cbb932f97355..27851fb0e25b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -1149,7 +1149,7 @@ int amdgpu_driver_open_kms(struct drm_device 
*dev, struct drm_file *file_priv)

  {
  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_fpriv *fpriv;
-    int r, pasid;
+    int r;
    /* Ensure IB tests are run on ring */
  flush_delayed_work(>delayed_init_work);
@@ -1172,15 +1172,9 @@ int amdgpu_driver_open_kms(struct drm_device 
*dev, struct drm_file *file_priv)

  goto out_suspend;
  }
  -    pasid = amdgpu_pasid_alloc(16);
-    if (pasid < 0) {
-    dev_warn(adev->dev, "No more PASIDs available!");
-    pasid = 0;
-    }
-
-    r = amdgpu_vm_init(adev, >vm, pasid);
+    r = amdgpu_vm_init(adev, >vm);
  if (r)
-    goto error_pasid;
+    goto free_fpriv;
    fpriv->prt_va = amdgpu_vm_bo_add(adev, >vm, NULL);
  if (!fpriv->prt_va) {
@@ -1208,10 +1202,7 @@ int amdgpu_driver_open_kms(struct drm_device 
*dev, struct drm_file *file_priv)

  error_vm:
  amdgpu_vm_fini(adev, >vm);
  -error_pasid:
-    if (pasid)
-    amdgpu_pasid_free(pasid);
-
+free_fpriv:
  kfree(fpriv);
    out_suspend:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

index 63975bda8e76..562c2c48a3a3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -87,6 +87,69 @@ struct amdgpu_prt_cb {
  struct dma_fence_cb cb;
  };
  +static int amdgpu_vm_pasid_alloc(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm, unsigned int pasid)
+{
+    unsigned long flags;
+    int r;
+
+    if (!pasid)
+    return 0;
+
+    spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    r = idr_alloc(>vm_manager.pasid_idr, vm, pasid, pasid + 1,
+  GFP_ATOMIC);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+    if (r < 0)
+    return r;
+
+    vm->pasid = pasid;
+    return 0;
+}
+static void amdgpu_vm_pasid_remove_id(struct amdgpu_device *adev,
+  unsigned int pasid)
+{
+    unsigned long flags;
+
+    if (!pasid)
+    return;
+
+    spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    idr_remove(>vm_manager.pasid_idr, pasid);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+
+}
+
+static void amdgpu_vm_pasid_remove(struct amdgpu_device *adev,
+   struct amdgpu_vm *vm)
+{
+    amdgpu_vm_pasid_remove_id(adev, vm->pasid);
+    vm->pasid = 0;
+}
+
+static void amdgpu_vm_pasid_free(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm)
+{
+    if (!vm->pasid)
+    return;
+
+    amdgpu_pasid_free(vm->pasid);
+    amdgpu_vm_pasid_remove(adev, vm);
+}
+
+static struct amdgpu_vm *amdgpu_vm_pasid_find(struct amdgpu_device 
*adev,

+  unsigned int pasid)
+{
+    struct amdgpu_vm *vm;
+    unsigned long flags;
+
+    spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    vm = idr_find(>vm_manager.pasid_idr, pasid);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+
+    return vm;
+}
+
  /*
   * vm eviction_lock can be taken in MMU notifiers. Make sure no 
reclaim-FS
   * happens while holding this lock anywhere to prevent deadlocks 
when
@@ -2859,17 +2922,17 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm 
*vm, long timeout)

   *
   * @adev: amdgpu_device pointer
   * @vm: requested vm
- * @pasid: Process address space identifier
   *
   * Init @vm fields.
   *
   * Returns:
   * 0 for success, error for failure.
   */
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm 
*vm, u32 pasid)

+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
  {
  struct amdgpu_bo *root_bo;
  struct amdgpu_bo_vm *root;
+    unsigned int pasid;
  int r, i;
    vm->va = RB_ROOT_CACHED;
@@ -2940,19 +3003,15 @@ int amdgpu_vm_init(struct amdgpu_device 
*adev, struct amdgpu_vm 

Re: [PATCH 1/1] drm/amdgpu: add helper function for vm pasid

2021-06-21 Thread Das, Nirmoy


On 6/21/2021 12:26 PM, Christian König wrote:
Well you completely break the handling in amdgpu_vm_handle_fault() 
with this.



I see one issue with:  if (!vm || (vm && vm->root.bo != root)) . I will 
split it and resend.


Am I missing something else ?


Regards,

Nirmoy





Christian.

Am 21.06.21 um 11:47 schrieb Das, Nirmoy:

ping.

On 6/17/2021 3:03 PM, Nirmoy Das wrote:

Cleanup code related to vm pasid by adding helper function.
This reduces lots code duplication.

Signed-off-by: Nirmoy Das 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |  17 +--
  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c  | 176 


  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h  |   2 +-
  3 files changed, 96 insertions(+), 99 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c

index cbb932f97355..27851fb0e25b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -1149,7 +1149,7 @@ int amdgpu_driver_open_kms(struct drm_device 
*dev, struct drm_file *file_priv)

  {
  struct amdgpu_device *adev = drm_to_adev(dev);
  struct amdgpu_fpriv *fpriv;
-    int r, pasid;
+    int r;
    /* Ensure IB tests are run on ring */
  flush_delayed_work(>delayed_init_work);
@@ -1172,15 +1172,9 @@ int amdgpu_driver_open_kms(struct drm_device 
*dev, struct drm_file *file_priv)

  goto out_suspend;
  }
  -    pasid = amdgpu_pasid_alloc(16);
-    if (pasid < 0) {
-    dev_warn(adev->dev, "No more PASIDs available!");
-    pasid = 0;
-    }
-
-    r = amdgpu_vm_init(adev, >vm, pasid);
+    r = amdgpu_vm_init(adev, >vm);
  if (r)
-    goto error_pasid;
+    goto free_fpriv;
    fpriv->prt_va = amdgpu_vm_bo_add(adev, >vm, NULL);
  if (!fpriv->prt_va) {
@@ -1208,10 +1202,7 @@ int amdgpu_driver_open_kms(struct drm_device 
*dev, struct drm_file *file_priv)

  error_vm:
  amdgpu_vm_fini(adev, >vm);
  -error_pasid:
-    if (pasid)
-    amdgpu_pasid_free(pasid);
-
+free_fpriv:
  kfree(fpriv);
    out_suspend:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

index 63975bda8e76..562c2c48a3a3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -87,6 +87,69 @@ struct amdgpu_prt_cb {
  struct dma_fence_cb cb;
  };
  +static int amdgpu_vm_pasid_alloc(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm, unsigned int pasid)
+{
+    unsigned long flags;
+    int r;
+
+    if (!pasid)
+    return 0;
+
+    spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    r = idr_alloc(>vm_manager.pasid_idr, vm, pasid, pasid + 1,
+  GFP_ATOMIC);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+    if (r < 0)
+    return r;
+
+    vm->pasid = pasid;
+    return 0;
+}
+static void amdgpu_vm_pasid_remove_id(struct amdgpu_device *adev,
+  unsigned int pasid)
+{
+    unsigned long flags;
+
+    if (!pasid)
+    return;
+
+    spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    idr_remove(>vm_manager.pasid_idr, pasid);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+
+}
+
+static void amdgpu_vm_pasid_remove(struct amdgpu_device *adev,
+   struct amdgpu_vm *vm)
+{
+    amdgpu_vm_pasid_remove_id(adev, vm->pasid);
+    vm->pasid = 0;
+}
+
+static void amdgpu_vm_pasid_free(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm)
+{
+    if (!vm->pasid)
+    return;
+
+    amdgpu_pasid_free(vm->pasid);
+    amdgpu_vm_pasid_remove(adev, vm);
+}
+
+static struct amdgpu_vm *amdgpu_vm_pasid_find(struct amdgpu_device 
*adev,

+  unsigned int pasid)
+{
+    struct amdgpu_vm *vm;
+    unsigned long flags;
+
+    spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+    vm = idr_find(>vm_manager.pasid_idr, pasid);
+ spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+
+    return vm;
+}
+
  /*
   * vm eviction_lock can be taken in MMU notifiers. Make sure no 
reclaim-FS

   * happens while holding this lock anywhere to prevent deadlocks when
@@ -2859,17 +2922,17 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm 
*vm, long timeout)

   *
   * @adev: amdgpu_device pointer
   * @vm: requested vm
- * @pasid: Process address space identifier
   *
   * Init @vm fields.
   *
   * Returns:
   * 0 for success, error for failure.
   */
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm 
*vm, u32 pasid)

+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
  {
  struct amdgpu_bo *root_bo;
  struct amdgpu_bo_vm *root;
+    unsigned int pasid;
  int r, i;
    vm->va = RB_ROOT_CACHED;
@@ -2940,19 +3003,15 @@ int amdgpu_vm_init(struct amdgpu_device 
*adev, struct amdgpu_vm *vm, u32 pasid)

    amdgpu_bo_unreserve(vm->root.bo);
  -    if (pasid) {
-    unsigned long flags;
-
- spin_lock_irqsave(>vm_manager.pasid_lock, flags);
-    r = 

Re: [PATCH 3/3] drm/amdgpu: wait for moving fence after pinning

2021-06-21 Thread Daniel Vetter
On Mon, Jun 21, 2021 at 03:03:28PM +0200, Christian König wrote:
> We actually need to wait for the moving fence after pinning
> the BO to make sure that the pin is completed.
> 
> Signed-off-by: Christian König 
> CC: sta...@kernel.org
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 14 +-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
> index baa980a477d9..37ec59365080 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
> @@ -214,9 +214,21 @@ static int amdgpu_dma_buf_pin(struct dma_buf_attachment 
> *attach)
>  {
>   struct drm_gem_object *obj = attach->dmabuf->priv;
>   struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
> + int r;
>  
>   /* pin buffer into GTT */
> - return amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT);
> + r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT);
> + if (r)
> + return r;
> +
> + if (bo->tbo.moving) {

dma-buf.c guarantees we have the reservation here, so we're fine.

Reviewed-by: Daniel Vetter 

> + r = dma_fence_wait(bo->tbo.moving, true);
> + if (r) {
> + amdgpu_bo_unpin(bo);
> + return r;
> + }
> + }
> + return 0;
>  }
>  
>  /**
> -- 
> 2.25.1
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH 2/3] drm/radeon: wait for moving fence after pinning

2021-06-21 Thread Daniel Vetter
On Mon, Jun 21, 2021 at 03:03:27PM +0200, Christian König wrote:
> We actually need to wait for the moving fence after pinning
> the BO to make sure that the pin is completed.
> 
> Signed-off-by: Christian König 
> CC: sta...@kernel.org
> ---
>  drivers/gpu/drm/radeon/radeon_prime.c | 16 +---
>  1 file changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/radeon_prime.c 
> b/drivers/gpu/drm/radeon/radeon_prime.c
> index 42a87948e28c..4a90807351e7 100644
> --- a/drivers/gpu/drm/radeon/radeon_prime.c
> +++ b/drivers/gpu/drm/radeon/radeon_prime.c
> @@ -77,9 +77,19 @@ int radeon_gem_prime_pin(struct drm_gem_object *obj)
>  
>   /* pin buffer into GTT */
>   ret = radeon_bo_pin(bo, RADEON_GEM_DOMAIN_GTT, NULL);
> - if (likely(ret == 0))
> - bo->prime_shared_count++;
> -
> + if (unlikely(ret))
> + goto error;
> +
> + if (bo->tbo.moving) {
> + ret = dma_fence_wait(bo->tbo.moving, false);

Here we wait whil holding the reservation, so we should be all fine. Maybe
not the nicest to wait while locked, but also I don't think it'll matter.

Reviewed-by: Daniel Vetter 

> + if (unlikely(ret)) {
> + radeon_bo_unpin(bo);
> + goto error;
> + }
> + }
> +
> + bo->prime_shared_count++;
> +error:
>   radeon_bo_unreserve(bo);
>   return ret;
>  }
> -- 
> 2.25.1
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH 1/3] drm/nouveau: wait for moving fence after pinning

2021-06-21 Thread Daniel Vetter
On Mon, Jun 21, 2021 at 03:03:26PM +0200, Christian König wrote:
> We actually need to wait for the moving fence after pinning
> the BO to make sure that the pin is completed.
> 
> Signed-off-by: Christian König 
> CC: sta...@kernel.org
> ---
>  drivers/gpu/drm/nouveau/nouveau_prime.c | 8 +++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c 
> b/drivers/gpu/drm/nouveau/nouveau_prime.c
> index 347488685f74..591738545eba 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_prime.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c
> @@ -93,7 +93,13 @@ int nouveau_gem_prime_pin(struct drm_gem_object *obj)
>   if (ret)
>   return -EINVAL;
>  
> - return 0;
> + if (nvbo->bo.moving) {

Don't we need to hold the dma_resv to read this? We can grab a reference
and then unlock, but I think just unlocked wait can go boom pretty easily
(since we don't hold a reference or lock so someone else can jump in and
free the moving fence).
-Daniel

> + ret = dma_fence_wait(nvbo->bo.moving, true);
> + if (ret)
> + nouveau_bo_unpin(nvbo);
> + }
> +
> + return ret;
>  }
>  
>  void nouveau_gem_prime_unpin(struct drm_gem_object *obj)
> -- 
> 2.25.1
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH] drm/radeon: Fix NULL dereference when updating memory stats

2021-06-21 Thread kernel test robot
Hi Mikel,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on next-20210618]
[cannot apply to linus/master v5.13-rc7 v5.13-rc6 v5.13-rc5 v5.13-rc7]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:
https://github.com/0day-ci/linux/commits/Mikel-Rychliski/drm-radeon-Fix-NULL-dereference-when-updating-memory-stats/20210621-091140
base:e71e3a48a7e89fa71fb70bf4602367528864d2ff
config: mips-allyesconfig (attached as .config)
compiler: mips-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# 
https://github.com/0day-ci/linux/commit/e5ec8682645a1ee2553fcb073d000802c11d2cb5
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review 
Mikel-Rychliski/drm-radeon-Fix-NULL-dereference-when-updating-memory-stats/20210621-091140
git checkout e5ec8682645a1ee2553fcb073d000802c11d2cb5
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross 
ARCH=mips 

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

All errors (new ones prefixed by >>):

>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/accessibility/speakup/speakup_decpc.ko',
>>  needed by '__modinst'.
>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/base/test/test_async_driver_probe.ko',
>>  needed by '__modinst'.
>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/i2c/i2c-stub.ko',
>>  needed by '__modinst'.
>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_nandbiterrs.ko',
>>  needed by '__modinst'.
>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_nandecctest.ko',
>>  needed by '__modinst'.
>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_oobtest.ko',
>>  needed by '__modinst'.
>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_pagetest.ko',
>>  needed by '__modinst'.
>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_readtest.ko',
>>  needed by '__modinst'.
>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_speedtest.ko',
>>  needed by '__modinst'.
>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_stresstest.ko',
>>  needed by '__modinst'.
>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_subpagetest.ko',
>>  needed by '__modinst'.
>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/mtd/tests/mtd_torturetest.ko',
>>  needed by '__modinst'.
>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/ntb/hw/epf/ntb_hw_epf.ko',
>>  needed by '__modinst'.
>> make[2]: *** No rule to make target 
>> '/tmp/kernel/mips-allyesconfig/gcc-9.3.0/e5ec8682645a1ee2553fcb073d000802c11d2cb5/lib/modules/5.13.0-rc6-next-20210618+/kernel/drivers/scsi/mpi3mr/mpi3mr.ko',
>>  needed by '__modinst'.
>&g

Re: [PATCH v3 1/2] habanalabs: define uAPI to export FD for DMA-BUF

2021-06-21 Thread Jason Gunthorpe
On Mon, Jun 21, 2021 at 02:28:48PM +0200, Daniel Vetter wrote:

> Mission acomplished, we've gone full circle, and the totally-not-a-gpu
> driver is now trying to use gpu infrastructure. And seems to have
> gained vram meanwhile too. Next up is going to be synchronization
> using dma_fence so you can pass buffers back without stalls
> among drivers.

Well, we can't even see the other side of this so who knows

This is a new uAPI, where is the userspace? In RDMA at least I require
to see the new userspace and test suite before changes to
include/uapi/rdma can go ahead.

> Doug/Jason from infiniband: Should we add linux-rdma to the dma-buf
> wildcard match so that you can catch these next time around too? At
> least when people use scripts/get_maintainers.pl correctly. All the
> other subsystems using dma-buf are on there already (dri-devel,
> linux-media and linaro-mm-sig for android/arm embedded stuff).

My bigger concern is this doesn't seem to be implementing PCI P2P DMA
correctly. This is following the same hacky NULL page approach that
Christoph Hellwig already NAK'd for AMD.

This should not be allowed to proliferate.

I would be much happier seeing this be done using the approach of
Logan's series here:

https://lore.kernel.org/linux-block/20210513223203.5542-1-log...@deltatee.com/

Jason
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH v3 1/2] habanalabs: define uAPI to export FD for DMA-BUF

2021-06-21 Thread Daniel Vetter
On Mon, Jun 21, 2021 at 03:02:10PM +0200, Greg KH wrote:
> On Mon, Jun 21, 2021 at 02:28:48PM +0200, Daniel Vetter wrote:
> > On Fri, Jun 18, 2021 at 2:36 PM Oded Gabbay  wrote:
> > > User process might want to share the device memory with another
> > > driver/device, and to allow it to access it over PCIe (P2P).
> > >
> > > To enable this, we utilize the dma-buf mechanism and add a dma-buf
> > > exporter support, so the other driver can import the device memory and
> > > access it.
> > >
> > > The device memory is allocated using our existing allocation uAPI,
> > > where the user will get a handle that represents the allocation.
> > >
> > > The user will then need to call the new
> > > uAPI (HL_MEM_OP_EXPORT_DMABUF_FD) and give the handle as a parameter.
> > >
> > > The driver will return a FD that represents the DMA-BUF object that
> > > was created to match that allocation.
> > >
> > > Signed-off-by: Oded Gabbay 
> > > Reviewed-by: Tomer Tayar 
> > 
> > Mission acomplished, we've gone full circle, and the totally-not-a-gpu
> > driver is now trying to use gpu infrastructure. And seems to have
> > gained vram meanwhile too. Next up is going to be synchronization
> > using dma_fence so you can pass buffers back without stalls
> > among drivers.
> 
> What's wrong with other drivers using dmabufs and even dma_fence?  It's
> a common problem when shuffling memory around systems, why is that
> somehow only allowed for gpu drivers?
> 
> There are many users of these structures in the kernel today that are
> not gpu drivers (tee, fastrpc, virtio, xen, IB, etc) as this is a common
> thing that drivers want to do (throw chunks of memory around from
> userspace to hardware).
> 
> I'm not trying to be a pain here, but I really do not understand why
> this is a problem.  A kernel api is present, why not use it by other
> in-kernel drivers?  We had the problem in the past where subsystems were
> trying to create their own interfaces for the same thing, which is why
> you all created the dmabuf api to help unify this.

It's the same thing as ever. 90% of an accel driver are in userspace,
that's where all the fun is, that's where the big picture review needs to
happen, and we've very conveniently bypassed all that a few years back
because it was too annoying.

Once we have the full driver stack and can start reviewing it I have no
objections to totally-not-gpus using all this stuff too. But until we can
do that this is all just causing headaches.

Ofc if you assume that userspace doesn't matter then you don't care, which
is where this giantic disconnect comes from.

Also unless we're actually doing this properly there's zero incentive for
me to review the kernel code and check whether it follows the rules
correctly, so you have excellent chances that you just break the rules.
And dma_buf/fence are tricky enough that you pretty much guaranteed to
break the rules if you're not involved in the discussions. Just now we
have a big one where everyone involved (who's been doing this for 10+
years all at least) realizes we've fucked up big time.

Anyway we've had this discussion, we're not going to move anyone here at
all, so *shrug*. I'll keep seeing accelarators in drivers/misc as blantant
bypassing of review by actual accelerator pieces, you keep seing dri-devel
as ... well I dunno, people who don't know what they're talking about
maybe. Or not relevant to your totally-not-a-gpu thing.

> > Also I'm wondering which is the other driver that we share buffers
> > with. The gaudi stuff doesn't have real struct pages as backing
> > storage, it only fills out the dma_addr_t. That tends to blow up with
> > other drivers, and the only place where this is guaranteed to work is
> > if you have a dynamic importer which sets the allow_peer2peer flag.
> > Adding maintainers from other subsystems who might want to chime in
> > here. So even aside of the big question as-is this is broken.
> 
> From what I can tell this driver is sending the buffers to other
> instances of the same hardware, as that's what is on the other "end" of
> the network connection.  No different from IB's use of RDMA, right?

There's no import afaict, but maybe I missed it. Assuming I haven't missed
it the importing necessarily has to happen by some other drivers.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH v3 1/2] habanalabs: define uAPI to export FD for DMA-BUF

2021-06-21 Thread Jason Gunthorpe
On Mon, Jun 21, 2021 at 03:02:10PM +0200, Greg KH wrote:
> On Mon, Jun 21, 2021 at 02:28:48PM +0200, Daniel Vetter wrote:

> > Also I'm wondering which is the other driver that we share buffers
> > with. The gaudi stuff doesn't have real struct pages as backing
> > storage, it only fills out the dma_addr_t. That tends to blow up with
> > other drivers, and the only place where this is guaranteed to work is
> > if you have a dynamic importer which sets the allow_peer2peer flag.
> > Adding maintainers from other subsystems who might want to chime in
> > here. So even aside of the big question as-is this is broken.
> 
> From what I can tell this driver is sending the buffers to other
> instances of the same hardware,

A dmabuf is consumed by something else in the kernel calling
dma_buf_map_attachment() on the FD.

What is the other side of this? I don't see any
dma_buf_map_attachment() calls in drivers/misc, or added in this patch
set.

AFAIK the only viable in-tree other side is in mlx5 (look in
umem_dmabuf.c)

Though as we already talked habana has their own networking (out of
tree, presumably) so I suspect this is really to support some out of
tree stuff??

Jason
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH 1/1] drm/amdgpu: add helper function for vm pasid

2021-06-21 Thread Das, Nirmoy

ping.

On 6/17/2021 3:03 PM, Nirmoy Das wrote:

Cleanup code related to vm pasid by adding helper function.
This reduces lots code duplication.

Signed-off-by: Nirmoy Das 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |  17 +--
  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c  | 176 
  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h  |   2 +-
  3 files changed, 96 insertions(+), 99 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index cbb932f97355..27851fb0e25b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -1149,7 +1149,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct 
drm_file *file_priv)
  {
struct amdgpu_device *adev = drm_to_adev(dev);
struct amdgpu_fpriv *fpriv;
-   int r, pasid;
+   int r;
  
  	/* Ensure IB tests are run on ring */

flush_delayed_work(>delayed_init_work);
@@ -1172,15 +1172,9 @@ int amdgpu_driver_open_kms(struct drm_device *dev, 
struct drm_file *file_priv)
goto out_suspend;
}
  
-	pasid = amdgpu_pasid_alloc(16);

-   if (pasid < 0) {
-   dev_warn(adev->dev, "No more PASIDs available!");
-   pasid = 0;
-   }
-
-   r = amdgpu_vm_init(adev, >vm, pasid);
+   r = amdgpu_vm_init(adev, >vm);
if (r)
-   goto error_pasid;
+   goto free_fpriv;
  
  	fpriv->prt_va = amdgpu_vm_bo_add(adev, >vm, NULL);

if (!fpriv->prt_va) {
@@ -1208,10 +1202,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, 
struct drm_file *file_priv)
  error_vm:
amdgpu_vm_fini(adev, >vm);
  
-error_pasid:

-   if (pasid)
-   amdgpu_pasid_free(pasid);
-
+free_fpriv:
kfree(fpriv);
  
  out_suspend:

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 63975bda8e76..562c2c48a3a3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -87,6 +87,69 @@ struct amdgpu_prt_cb {
struct dma_fence_cb cb;
  };
  
+static int amdgpu_vm_pasid_alloc(struct amdgpu_device *adev,

+struct amdgpu_vm *vm, unsigned int pasid)
+{
+   unsigned long flags;
+   int r;
+
+   if (!pasid)
+   return 0;
+
+   spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+   r = idr_alloc(>vm_manager.pasid_idr, vm, pasid, pasid + 1,
+ GFP_ATOMIC);
+   spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+   if (r < 0)
+   return r;
+
+   vm->pasid = pasid;
+   return 0;
+}
+static void amdgpu_vm_pasid_remove_id(struct amdgpu_device *adev,
+ unsigned int pasid)
+{
+   unsigned long flags;
+
+   if (!pasid)
+   return;
+
+   spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+   idr_remove(>vm_manager.pasid_idr, pasid);
+   spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+
+}
+
+static void amdgpu_vm_pasid_remove(struct amdgpu_device *adev,
+  struct amdgpu_vm *vm)
+{
+   amdgpu_vm_pasid_remove_id(adev, vm->pasid);
+   vm->pasid = 0;
+}
+
+static void amdgpu_vm_pasid_free(struct amdgpu_device *adev,
+struct amdgpu_vm *vm)
+{
+   if (!vm->pasid)
+   return;
+
+   amdgpu_pasid_free(vm->pasid);
+   amdgpu_vm_pasid_remove(adev, vm);
+}
+
+static struct amdgpu_vm *amdgpu_vm_pasid_find(struct amdgpu_device *adev,
+ unsigned int pasid)
+{
+   struct amdgpu_vm *vm;
+   unsigned long flags;
+
+   spin_lock_irqsave(>vm_manager.pasid_lock, flags);
+   vm = idr_find(>vm_manager.pasid_idr, pasid);
+   spin_unlock_irqrestore(>vm_manager.pasid_lock, flags);
+
+   return vm;
+}
+
  /*
   * vm eviction_lock can be taken in MMU notifiers. Make sure no reclaim-FS
   * happens while holding this lock anywhere to prevent deadlocks when
@@ -2859,17 +2922,17 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long 
timeout)
   *
   * @adev: amdgpu_device pointer
   * @vm: requested vm
- * @pasid: Process address space identifier
   *
   * Init @vm fields.
   *
   * Returns:
   * 0 for success, error for failure.
   */
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid)
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
  {
struct amdgpu_bo *root_bo;
struct amdgpu_bo_vm *root;
+   unsigned int pasid;
int r, i;
  
  	vm->va = RB_ROOT_CACHED;

@@ -2940,19 +3003,15 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct 
amdgpu_vm *vm, u32 pasid)
  
  	amdgpu_bo_unreserve(vm->root.bo);
  
-	if (pasid) {

-   unsigned long flags;
-
-   spin_lock_irqsave(>vm_manager.pasid_lock, flags);
-   r = idr_alloc(>vm_manager.pasid_idr, vm, pasid, 

  1   2   >