RE: [PATCH 2/2] drm/amdkfd: Adjust weight to represent num_hops info when report xgmi iolink

2019-04-22 Thread Xu, Feifei
Acked-by: Feifei Xu 

-Original Message-
From: amd-gfx  On Behalf Of Liu, Shaoyun
Sent: Thursday, April 18, 2019 2:59 AM
To: amd-gfx@lists.freedesktop.org
Cc: Liu, Shaoyun 
Subject: [PATCH 2/2] drm/amdkfd: Adjust weight to represent num_hops info when 
report xgmi iolink

Upper level runtime need the xgmi hops info to determine the data path

Change-Id: I969b419eab125157e223e9b03980ca229c1e6af4
Signed-off-by: shaoyunl 
---
 drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 8 ++--  
drivers/gpu/drm/amd/amdkfd/kfd_crat.h | 3 ++-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index 2e7c449..d48c6c5 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -341,6 +341,7 @@ static int kfd_parse_subtype_cache(struct 
crat_subtype_cache *cache,
return 0;
 }
 
+
 /* kfd_parse_subtype_iolink - parse iolink subtypes and attach it to correct
  * topology device present in the device_list
  */
@@ -372,7 +373,7 @@ static int kfd_parse_subtype_iolink(struct 
crat_subtype_iolink *iolink,
if (props->iolink_type == CRAT_IOLINK_TYPE_PCIEXPRESS)
props->weight = 20;
else if (props->iolink_type == CRAT_IOLINK_TYPE_XGMI)
-   props->weight = 15;
+   props->weight = 15 * iolink->num_hops_xgmi;
else
props->weight = node_distance(id_from, id_to);
 
@@ -1092,6 +1093,7 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int 
*avail_size,
 
 static int kfd_fill_gpu_xgmi_link_to_gpu(int *avail_size,
struct kfd_dev *kdev,
+   struct kfd_dev *peer_kdev,
struct crat_subtype_iolink *sub_type_hdr,
uint32_t proximity_domain_from,
uint32_t proximity_domain_to)
@@ -1110,6 +1112,8 @@ static int kfd_fill_gpu_xgmi_link_to_gpu(int *avail_size,
sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_XGMI;
sub_type_hdr->proximity_domain_from = proximity_domain_from;
sub_type_hdr->proximity_domain_to = proximity_domain_to;
+   sub_type_hdr->num_hops_xgmi =
+   amdgpu_amdkfd_get_xgmi_hops_count(kdev->kgd, peer_kdev->kgd);
return 0;
 }
 
@@ -1287,7 +1291,7 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
(char *)sub_type_hdr +
sizeof(struct crat_subtype_iolink));
ret = kfd_fill_gpu_xgmi_link_to_gpu(
-   &avail_size, kdev,
+   &avail_size, kdev, peer_dev->gpu,
(struct crat_subtype_iolink *)sub_type_hdr,
proximity_domain, nid);
if (ret < 0)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h 
b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
index 7c3f192..579835c 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
@@ -257,7 +257,7 @@ struct crat_subtype_ccompute {
 #define CRAT_IOLINK_TYPE_OTHER 16
 #define CRAT_IOLINK_TYPE_MAX   255
 
-#define CRAT_IOLINK_RESERVED_LENGTH24
+#define CRAT_IOLINK_RESERVED_LENGTH20
 
 struct crat_subtype_iolink {
uint8_t type;
@@ -274,6 +274,7 @@ struct crat_subtype_iolink {
uint32_tminimum_bandwidth_mbs;
uint32_tmaximum_bandwidth_mbs;
uint32_trecommended_transfer_size;
+   uint32_tnum_hops_xgmi;
uint8_t reserved2[CRAT_IOLINK_RESERVED_LENGTH];
 };
 
--
2.7.4

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

Re: [PATCH v5 1/6] drm/amd/display: wait for fence without holding reservation lock

2019-04-22 Thread Dieter Nützel

Hello Andrey,

this series can't apply (brake on #3) on top of amd-staging-drm-next.
v2 works (Thu, 11 Apr 2019).

Dieter

Am 18.04.2019 17:00, schrieb Andrey Grodzovsky:

From: Christian König 

Don't block others while waiting for the fences to finish, concurrent
submission is perfectly valid in this case and holding the lock can
prevent killed applications from terminating.

Signed-off-by: Christian König 
Reviewed-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

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 380a7f9..ad4f0e5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4814,23 +4814,26 @@ static void amdgpu_dm_commit_planes(struct
drm_atomic_state *state,
continue;
}

+   abo = gem_to_amdgpu_bo(fb->obj[0]);
+
+   /* Wait for all fences on this FB */
+   r = reservation_object_wait_timeout_rcu(abo->tbo.resv, true,
+   false,
+   MAX_SCHEDULE_TIMEOUT);
+   WARN_ON(r < 0);
+
/*
 * TODO This might fail and hence better not used, wait
 * explicitly on fences instead
 * and in general should be called for
 * blocking commit to as per framework helpers
 */
-   abo = gem_to_amdgpu_bo(fb->obj[0]);
r = amdgpu_bo_reserve(abo, true);
if (unlikely(r != 0)) {
DRM_ERROR("failed to reserve buffer before flip\n");
WARN_ON(1);
}

-   /* Wait for all fences on this FB */
-		WARN_ON(reservation_object_wait_timeout_rcu(abo->tbo.resv, true, 
false,

-   
MAX_SCHEDULE_TIMEOUT) < 0);
-
amdgpu_bo_get_tiling_flags(abo, &tiling_flags);

amdgpu_bo_unreserve(abo);

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

[PATCH 2/3] drm/dp_mst: Expose build_mst_prop_path()

2019-04-22 Thread sunpeng.li
From: Leo Li 

To give identifiable attributes to MST DP aux devices, we can use the
MST relative address. Expose this function for later use.

Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 4 ++--
 include/drm/drm_dp_mst_helper.h   | 4 
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 2ab16c9..86ff8e2 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -1120,7 +1120,7 @@ static void drm_dp_check_mstb_guid(struct 
drm_dp_mst_branch *mstb, u8 *guid)
}
 }
 
-static void build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
+void drm_dp_build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
int pnum,
char *proppath,
size_t proppath_size)
@@ -1202,7 +1202,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch 
*mstb,
if (created && !port->input) {
char proppath[255];
 
-   build_mst_prop_path(mstb, port->port_num, proppath, 
sizeof(proppath));
+   drm_dp_build_mst_prop_path(mstb, port->port_num, proppath, 
sizeof(proppath));
port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, 
port, proppath);
if (!port->connector) {
/* remove it from the port list */
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 371cc28..81c8d79 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -602,6 +602,10 @@ void drm_dp_mst_deallocate_vcpi(struct 
drm_dp_mst_topology_mgr *mgr,
 int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr,
   int pbn);
 
+void drm_dp_build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
+  int pnum,
+  char *proppath,
+  size_t proppath_size);
 
 int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr);
 
-- 
2.7.4

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

[PATCH 3/3] drm/dp_mst: Register AUX devices for MST ports

2019-04-22 Thread sunpeng.li
From: Ville Syrjälä 

All available downstream ports - physical and logical - are exposed for
each MST device. They are listed in /dev/, following the same naming
scheme as SST devices by appending an incremental ID.

Additionally, a 'path' attribute is attached to the device. This is to
allow udev to provide more identifiable symlinks to these devices,
similar to /dev/disks. For example, adding the following udev rule:

SUBSYSTEMS=="drm_dp_aux_dev", ATTR{path}=="?*", 
SYMLINK+="drm_dp_aux/by-path/$attr{path}"

With a MST topology like so:

   +-+
   |  ASIC   |
   +-+
  Conn-0|
|
   +v+
  +| MST HUB |+
  |+-+|
  |   |
  |Port-1   Port-2|
+-v-+   +-v-+
|  MST  |   |  SST  |
|  Display  |   |  Display  |
+---+   +---+
  |Port-1
  x

Will create the following symlinks in 'drm_dp_aux/by-path/':

AUX Device Name   | MST Device
--+--
card0_sst:0 (*)   | MST Hub
card0_mst:0-1 | MST Display
card0_mst:0-1-1   | MST Display's disconnected DP out
card0_mst:0-1-8   | MST Display's internal sink
card0_mst:0-2 | SST Display

(*) Note that the first digit is suppose to mean 'Connector ID'.
However, that's only true for 'mst:' paths. A TODO item has been left to
address this.

Although all downstream ports are exposed, only some will work. On
certain MST displays, the upstream physical port will ACK DPCD reads.
However, reads on the local logical port to the internal sink will
*NAK*. i.e. reading mst:0-1 ACKs, but mst:0-1-8 NAKs.

There may also be duplicates. Some displays will return the same GUID
when reading DPCD from both mst:0-1 and mst:0-1-8.

There are some device-dependent behavior as well. The MST hub used
during testing will actually *ACK* read requests on a disconnected
physical port, whereas the MST displays will NAK.

In light of these discrepancies, it's simpler to expose all downstream
ports - both physical and logical - and let the user decide what to use.

Signed-off-by: Ville Syrjälä 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_dp_aux_dev.c  |  53 -
 drivers/gpu/drm/drm_dp_mst_topology.c | 103 +-
 include/drm/drm_dp_helper.h   |   4 ++
 include/drm/drm_dp_mst_helper.h   |   6 ++
 4 files changed, 151 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 6d84611..4218bbf 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -114,10 +115,50 @@ static ssize_t name_show(struct device *dev,
 
return res;
 }
+
+static int is_drm_primary_device(struct device *dev, void *data)
+{
+   return strstr(dev_name(dev), "card") != NULL;
+}
+
+static ssize_t path_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct drm_dp_aux_dev *aux_dev =
+   drm_dp_aux_dev_get_by_minor(MINOR(dev->devt));
+   struct drm_dp_aux *aux = aux_dev->aux;
+   struct drm_dp_mst_port *port;
+   struct device *card;
+   char temp[64];
+   ssize_t res;
+
+   card = device_find_child(dev->parent, NULL,
+is_drm_primary_device);
+
+   if (!aux->is_remote) {
+   /*
+* TODO: AUX index does not correlate with connector ID. See if
+* connector ID can be used instead.
+*/
+   res = sprintf(buf, "%s_%s:%d\n",
+ dev_name(card), "sst", aux_dev->index);
+   return res;
+   }
+
+   port = container_of(aux, struct drm_dp_mst_port, aux);
+   drm_dp_build_mst_prop_path(port->parent, port->port_num,
+  temp, sizeof(temp));
+   res = sprintf(buf, "%s_%s\n", dev_name(card), temp);
+
+   return res;
+}
+
 static DEVICE_ATTR_RO(name);
+static DEVICE_ATTR_RO(path);
 
 static struct attribute *drm_dp_aux_attrs[] = {
&dev_attr_name.attr,
+   &dev_attr_path.attr,
NULL,
 };
 ATTRIBUTE_GROUPS(drm_dp_aux);
@@ -160,7 +201,11 @@ static ssize_t auxdev_read_iter(struct kiocb *iocb, struct 
iov_iter *to)
break;
}
 
-   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+   if (aux_dev->aux->is_remote)
+   res = drm_dp_mst_dpcd_read(aux_dev->aux, pos, buf, 
todo);
+   else
+   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+
if (res <= 0)
break;
 
@@ -207,7 +252,11 @@ static ssize_t auxdev_write_iter(str

[PATCH 1/3] drm/dp: Use non-cyclic idr

2019-04-22 Thread sunpeng.li
From: Leo Li 

In preparation for adding aux devices for DP MST, make the IDR
non-cyclic. That way, hotplug cycling MST devices won't needlessly
increment the minor version index.

Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_dp_aux_dev.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 0e4f25d..6d84611 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -80,8 +80,7 @@ static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct 
drm_dp_aux *aux)
kref_init(&aux_dev->refcount);
 
mutex_lock(&aux_idr_mutex);
-   index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS,
-GFP_KERNEL);
+   index = idr_alloc(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, GFP_KERNEL);
mutex_unlock(&aux_idr_mutex);
if (index < 0) {
kfree(aux_dev);
-- 
2.7.4

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

Re: [PATCH 2/2] drm/amdkfd: Adjust weight to represent num_hops info when report xgmi iolink

2019-04-22 Thread Liu, Shaoyun
ping .

Felix , can you help check this patch ?

Regards

shaoyun.liu

On 2019-04-17 2:59 p.m., Liu, Shaoyun wrote:
> Upper level runtime need the xgmi hops info to determine the data path
>
> Change-Id: I969b419eab125157e223e9b03980ca229c1e6af4
> Signed-off-by: shaoyunl 
> ---
>   drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 8 ++--
>   drivers/gpu/drm/amd/amdkfd/kfd_crat.h | 3 ++-
>   2 files changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c 
> b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
> index 2e7c449..d48c6c5 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
> @@ -341,6 +341,7 @@ static int kfd_parse_subtype_cache(struct 
> crat_subtype_cache *cache,
>   return 0;
>   }
>   
> +
>   /* kfd_parse_subtype_iolink - parse iolink subtypes and attach it to correct
>* topology device present in the device_list
>*/
> @@ -372,7 +373,7 @@ static int kfd_parse_subtype_iolink(struct 
> crat_subtype_iolink *iolink,
>   if (props->iolink_type == CRAT_IOLINK_TYPE_PCIEXPRESS)
>   props->weight = 20;
>   else if (props->iolink_type == CRAT_IOLINK_TYPE_XGMI)
> - props->weight = 15;
> + props->weight = 15 * iolink->num_hops_xgmi;
>   else
>   props->weight = node_distance(id_from, id_to);
>   
> @@ -1092,6 +1093,7 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int 
> *avail_size,
>   
>   static int kfd_fill_gpu_xgmi_link_to_gpu(int *avail_size,
>   struct kfd_dev *kdev,
> + struct kfd_dev *peer_kdev,
>   struct crat_subtype_iolink *sub_type_hdr,
>   uint32_t proximity_domain_from,
>   uint32_t proximity_domain_to)
> @@ -1110,6 +1112,8 @@ static int kfd_fill_gpu_xgmi_link_to_gpu(int 
> *avail_size,
>   sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_XGMI;
>   sub_type_hdr->proximity_domain_from = proximity_domain_from;
>   sub_type_hdr->proximity_domain_to = proximity_domain_to;
> + sub_type_hdr->num_hops_xgmi =
> + amdgpu_amdkfd_get_xgmi_hops_count(kdev->kgd, peer_kdev->kgd);
>   return 0;
>   }
>   
> @@ -1287,7 +1291,7 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
>   (char *)sub_type_hdr +
>   sizeof(struct crat_subtype_iolink));
>   ret = kfd_fill_gpu_xgmi_link_to_gpu(
> - &avail_size, kdev,
> + &avail_size, kdev, peer_dev->gpu,
>   (struct crat_subtype_iolink *)sub_type_hdr,
>   proximity_domain, nid);
>   if (ret < 0)
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h 
> b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
> index 7c3f192..579835c 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
> @@ -257,7 +257,7 @@ struct crat_subtype_ccompute {
>   #define CRAT_IOLINK_TYPE_OTHER  16
>   #define CRAT_IOLINK_TYPE_MAX255
>   
> -#define CRAT_IOLINK_RESERVED_LENGTH  24
> +#define CRAT_IOLINK_RESERVED_LENGTH  20
>   
>   struct crat_subtype_iolink {
>   uint8_t type;
> @@ -274,6 +274,7 @@ struct crat_subtype_iolink {
>   uint32_tminimum_bandwidth_mbs;
>   uint32_tmaximum_bandwidth_mbs;
>   uint32_trecommended_transfer_size;
> + uint32_tnum_hops_xgmi;
>   uint8_t reserved2[CRAT_IOLINK_RESERVED_LENGTH];
>   };
>   
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Re: [PATCH 1/2] drm/amdgpu: Implement get num of hops between two xgmi device

2019-04-22 Thread Liu, Shaoyun
ping

On 2019-04-17 2:58 p.m., Liu, Shaoyun wrote:
> KFD need to provide the info for upper level to determine the data path
>
> Change-Id: Idc809e8f3381b9222dd7be96539522d440f3ee7d
> Signed-off-by: shaoyunl 
> ---
>   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   | 21 +
>   drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h   |  2 ++
>   4 files changed, 39 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
> index acf8ae0..3fe9a38 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
> @@ -27,6 +27,7 @@
>   #include "amdgpu_gfx.h"
>   #include 
>   #include 
> +#include "amdgpu_xgmi.h"
>   
>   static const unsigned int compute_vmid_bitmap = 0xFF00;
>   
> @@ -481,6 +482,20 @@ uint64_t amdgpu_amdkfd_get_hive_id(struct kgd_dev *kgd)
>   
>   return adev->gmc.xgmi.hive_id;
>   }
> +uint32_t amdgpu_amdkfd_get_xgmi_hops_count(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_hops_count(adev, peer_adev);
> +
> + if (ret < 0) {
> + DRM_ERROR("amdgpu: failed to get  xgmi hops count 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  (uint32_t)ret;
> +}
>   
>   int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type 
> engine,
>   uint32_t vmid, uint64_t gpu_addr,
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
> index e6a5037..8cc8a5a1 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
> @@ -154,6 +154,7 @@ int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, 
> int dma_buf_fd,
> uint32_t *flags);
>   uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd);
>   uint64_t amdgpu_amdkfd_get_hive_id(struct kgd_dev *kgd);
> +uint32_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct 
> kgd_dev *src);
>   
>   #define read_user_wptr(mmptr, wptr, dst)\
>   ({  \
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
> index a48c84c..eaebd47 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
> @@ -248,6 +248,27 @@ int amdgpu_xgmi_update_topology(struct amdgpu_hive_info 
> *hive, struct amdgpu_dev
>   return ret;
>   }
>   
> +
> +int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev,
> + struct amdgpu_device *peer_adev)
> +{
> + struct psp_xgmi_topology_info *top;
> + int ret = 0;
> +
> + top = kzalloc(sizeof(struct psp_xgmi_topology_info), GFP_KERNEL);
> + if (!top)
> + return -ENOMEM;
> + top->num_nodes = 1;
> + top->nodes[0].node_id = peer_adev->gmc.xgmi.node_id;
> + ret = psp_xgmi_get_topology_info(&adev->psp, 1, top);
> + if (ret) {
> + dev_err(adev->dev,
> + "XGMI: Failed to get topology info\n");
> + return ret;
> + }
> + return top->nodes[0].num_hops;
> +}
> +
>   int amdgpu_xgmi_add_device(struct amdgpu_device *adev)
>   {
>   struct psp_xgmi_topology_info *hive_topology;
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
> index 3e9c91e..8a945bf 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
> @@ -41,6 +41,8 @@ int amdgpu_xgmi_update_topology(struct amdgpu_hive_info 
> *hive, struct amdgpu_dev
>   int amdgpu_xgmi_add_device(struct amdgpu_device *adev);
>   void 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);
>   
>   static inline bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev,
>   struct amdgpu_device *bo_adev)
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Re: [PATCH 1/2] drm/dp_aux: Use non-cyclic idr, add suffix option for aux device

2019-04-22 Thread Lyude Paul
On Wed, 2019-04-17 at 23:10 +, Li, Sun peng (Leo) wrote:
> 
> 
> On 2019-04-16 6:16 p.m., Lyude Paul wrote:
> > Sorry for the slow response, I've been really busy ;_;
> 
> No worries :)
> 
> > On Fri, 2019-04-12 at 12:05 -0400, sunpeng...@amd.com wrote:
> > > From: Leo Li 
> > > 
> > > In preparation for adding aux devices for DP MST:
> > > 
> > > 1. A non-cyclic idr is used for the device minor version. That way,
> > > hotplug cycling MST devices won't needlessly increment the minor
> > > version index.
> > 
> > I really like this btw, cyclic idrs are really annoying for drm_dp_aux_dev,
> > even outside of MST (try reloading a drm driver a couple of times and you'll
> > understand ;). I think we should split this into another commit though
> > 
> > > 2. A suffix option is added to the aux device file name. It can be used
> > > to identify the corresponding MST device.
> > 
> > I like this idea, but I think there may be a better way that we can do this.
> > Using /dev/nvme* as an example, we have the standard dev paths (/dev/nvme0,
> > /dev/nvme0n1, etc.). But we can also access them through /dev/disk/by-
> > {id,label,partlabel,partuuid,path,uuid}.
> > 
> > So what if we added something similar for aux devices? We start off with the
> > standard /dev/drm_dp_aux*, then provide more descriptive symlinks and
> > directories:
> > 
> > (feel free to come up with better naming then this if you can)
> > 
> > /dev/drm_dp_aux/card0-DP-1 -> /dev/drm_dp_aux1
> > /dev/drm_dp_aux/card0-DP-2 -> /dev/drm_dp_aux2
> > etc.
> 
> That does sound neater - although FWICT, this will have to be done with
> udev rules?
> 
> I took a brief look at how that's done for storage devices. It looks
> like they have rules defined in
> /lib/udev/rules.d/60-persistent-storage.rules that manages the "by-x"
> symlinks.
> 
> To make this happen for aux devices, what we could do is attach sysfs
> attributes to the device. It can then be parsed by udev in a similar
> fashion. Currently, only 'name' attribute is attached, as seen in
> drm_dp_aux_dev.c (after name_show()).

Yeah-that sounds perfect to me!

> 
> Thanks,
> Leo
> 
> > > Signed-off-by: Leo Li 
> > > ---
> > >   drivers/gpu/drm/drm_crtc_helper_internal.h | 5 +++--
> > >   drivers/gpu/drm/drm_dp_aux_dev.c   | 8 
> > >   drivers/gpu/drm/drm_dp_helper.c| 2 +-
> > >   3 files changed, 8 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/drm_crtc_helper_internal.h
> > > b/drivers/gpu/drm/drm_crtc_helper_internal.h
> > > index b5ac158..9f0907b 100644
> > > --- a/drivers/gpu/drm/drm_crtc_helper_internal.h
> > > +++ b/drivers/gpu/drm/drm_crtc_helper_internal.h
> > > @@ -46,7 +46,7 @@ static inline int drm_fb_helper_modinit(void)
> > >   #ifdef CONFIG_DRM_DP_AUX_CHARDEV
> > >   int drm_dp_aux_dev_init(void);
> > >   void drm_dp_aux_dev_exit(void);
> > > -int drm_dp_aux_register_devnode(struct drm_dp_aux *aux);
> > > +int drm_dp_aux_register_devnode(struct drm_dp_aux *aux, const char
> > > *suffix);
> > >   void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux);
> > >   #else
> > >   static inline int drm_dp_aux_dev_init(void)
> > > @@ -58,7 +58,8 @@ static inline void drm_dp_aux_dev_exit(void)
> > >   {
> > >   }
> > >   
> > > -static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
> > > +static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux,
> > > +   const char *suffix)
> > >   {
> > >   return 0;
> > >   }
> > > diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c
> > > b/drivers/gpu/drm/drm_dp_aux_dev.c
> > > index 0e4f25d..2310a67 100644
> > > --- a/drivers/gpu/drm/drm_dp_aux_dev.c
> > > +++ b/drivers/gpu/drm/drm_dp_aux_dev.c
> > > @@ -80,8 +80,7 @@ static struct drm_dp_aux_dev
> > > *alloc_drm_dp_aux_dev(struct
> > > drm_dp_aux *aux)
> > >   kref_init(&aux_dev->refcount);
> > >   
> > >   mutex_lock(&aux_idr_mutex);
> > > - index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS,
> > > -  GFP_KERNEL);
> > > + index = idr_alloc(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, GFP_KERNEL);
> > >   mutex_unlock(&aux_idr_mutex);
> > >   if (index < 0) {
> > >   kfree(aux_dev);
> > > @@ -290,7 +289,7 @@ void drm_dp_aux_unregister_devnode(struct drm_dp_aux
> > > *aux)
> > >   kref_put(&aux_dev->refcount, release_drm_dp_aux_dev);
> > >   }
> > >   
> > > -int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
> > > +int drm_dp_aux_register_devnode(struct drm_dp_aux *aux, const char
> > > *suffix)
> > >   {
> > >   struct drm_dp_aux_dev *aux_dev;
> > >   int res;
> > > @@ -301,7 +300,8 @@ int drm_dp_aux_register_devnode(struct drm_dp_aux
> > > *aux)
> > >   
> > >   aux_dev->dev = device_create(drm_dp_aux_dev_class, aux->dev,
> > >MKDEV(drm_dev_major, aux_dev-
> > > >index),
> > > NULL,
> > > - 

Re: [PATCH] drm/amdgpu: Check if smu.ppt_funcs is initialized before accessing

2019-04-22 Thread Li, Sun peng (Leo)
>>> -   if (adev->smu.ppt_funcs->get_current_power_state)
>>> +   if (adev->smu.ppt_funcs && adev->smu.ppt_funcs-
>>> get_current_power_state)
>>
>> For consistency, I think we probably want something like:
>> if (is_support_sw_smu(adev) && adev->smu.ppt_funcs-
>>> get_current_power_state)
>>
>> Either way:
>> Reviewed-by: Alex Deucher 
> 
> Yes. The same comment with me. Please use is_support_sw_smu() to check it.
> With that fixed, please add Reviewed-by: Huang Rui 
> 

Will modify and merge.

Thanks,
Leo

>>
>>>  pm = amdgpu_smu_get_current_power_state(adev);
>>>  else if (adev->powerplay.pp_funcs->get_current_power_state)
>>>  pm = amdgpu_dpm_get_current_power_state(adev);
>>> --
>>> 2.7.4
>>>
>>> ___
>>> amd-gfx mailing list
>>> amd-gfx@lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
>> ___
>> amd-gfx mailing list
>> amd-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Re: [PATCH v5 6/6] drm/amdgpu: Avoid HW reset if guilty job already signaled.

2019-04-22 Thread Chunming Zhou
+Monk.

GPU reset is used widely in SRIOV, so need virtulizatino guy take a look.

But out of curious, why guilty job can signal more if the job is already 
set to guilty? set it wrongly?


-David

在 2019/4/18 23:00, Andrey Grodzovsky 写道:
> Also reject TDRs if another one already running.
>
> v2:
> Stop all schedulers across device and entire XGMI hive before
> force signaling HW fences.
> Avoid passing job_signaled to helper fnctions to keep all the decision
> making about skipping HW reset in one place.
>
> v3:
> Fix SW sched. hang after non HW reset. sched.hw_rq_count has to be balanced
> against it's decrement in drm_sched_stop in non HW reset case.
> v4: rebase
> v5: Revert v3 as we do it now in sceduler code.
>
> Signed-off-by: Andrey Grodzovsky 
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 143 
> +++--
>   1 file changed, 95 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index a0e165c..85f8792 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -3334,8 +3334,6 @@ static int amdgpu_device_pre_asic_reset(struct 
> amdgpu_device *adev,
>   if (!ring || !ring->sched.thread)
>   continue;
>   
> - drm_sched_stop(&ring->sched, &job->base);
> -
>   /* after all hw jobs are reset, hw fence is meaningless, so 
> force_completion */
>   amdgpu_fence_driver_force_completion(ring);
>   }
> @@ -3343,6 +3341,7 @@ static int amdgpu_device_pre_asic_reset(struct 
> amdgpu_device *adev,
>   if(job)
>   drm_sched_increase_karma(&job->base);
>   
> + /* Don't suspend on bare metal if we are not going to HW reset the ASIC 
> */
>   if (!amdgpu_sriov_vf(adev)) {
>   
>   if (!need_full_reset)
> @@ -3480,37 +3479,21 @@ static int amdgpu_do_asic_reset(struct 
> amdgpu_hive_info *hive,
>   return r;
>   }
>   
> -static void amdgpu_device_post_asic_reset(struct amdgpu_device *adev)
> +static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, bool trylock)
>   {
> - int i;
> -
> - for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
> - struct amdgpu_ring *ring = adev->rings[i];
> -
> - if (!ring || !ring->sched.thread)
> - continue;
> -
> - if (!adev->asic_reset_res)
> - drm_sched_resubmit_jobs(&ring->sched);
> + if (trylock) {
> + if (!mutex_trylock(&adev->lock_reset))
> + return false;
> + } else
> + mutex_lock(&adev->lock_reset);
>   
> - drm_sched_start(&ring->sched, !adev->asic_reset_res);
> - }
> -
> - if (!amdgpu_device_has_dc_support(adev)) {
> - drm_helper_resume_force_mode(adev->ddev);
> - }
> -
> - adev->asic_reset_res = 0;
> -}
> -
> -static void amdgpu_device_lock_adev(struct amdgpu_device *adev)
> -{
> - mutex_lock(&adev->lock_reset);
>   atomic_inc(&adev->gpu_reset_counter);
>   adev->in_gpu_reset = 1;
>   /* Block kfd: SRIOV would do it separately */
>   if (!amdgpu_sriov_vf(adev))
>   amdgpu_amdkfd_pre_reset(adev);
> +
> + return true;
>   }
>   
>   static void amdgpu_device_unlock_adev(struct amdgpu_device *adev)
> @@ -3538,40 +3521,42 @@ static void amdgpu_device_unlock_adev(struct 
> amdgpu_device *adev)
>   int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
> struct amdgpu_job *job)
>   {
> - int r;
> + struct list_head device_list, *device_list_handle =  NULL;
> + bool need_full_reset, job_signaled;
>   struct amdgpu_hive_info *hive = NULL;
> - bool need_full_reset = false;
>   struct amdgpu_device *tmp_adev = NULL;
> - struct list_head device_list, *device_list_handle =  NULL;
> + int i, r = 0;
>   
> + need_full_reset = job_signaled = false;
>   INIT_LIST_HEAD(&device_list);
>   
>   dev_info(adev->dev, "GPU reset begin!\n");
>   
> + hive = amdgpu_get_xgmi_hive(adev, false);
> +
>   /*
> -  * In case of XGMI hive disallow concurrent resets to be triggered
> -  * by different nodes. No point also since the one node already 
> executing
> -  * reset will also reset all the other nodes in the hive.
> +  * Here we trylock to avoid chain of resets executing from
> +  * either trigger by jobs on different adevs in XGMI hive or jobs on
> +  * different schedulers for same device while this TO handler is 
> running.
> +  * We always reset all schedulers for device and all devices for XGMI
> +  * hive so that should take care of them too.
>*/
> - hive = amdgpu_get_xgmi_hive(adev, 0);
> - if (hive && adev->gmc.xgmi.num_physical_nodes > 1 &&
> - !mutex_trylock(&hive->reset_lock))
> +
> + if (hive && !mutex_trylock(&hive->reset_lock)) {
> + DRM_INFO("B

Re: [PATCH v5 4/6] drm/sched: Keep s_fence->parent pointer

2019-04-22 Thread Chunming Zhou
+Monk to response this patch.


在 2019/4/18 23:00, Andrey Grodzovsky 写道:
> For later driver's reference to see if the fence is signaled.
>
> v2: Move parent fence put to resubmit jobs.
>
> Signed-off-by: Andrey Grodzovsky 
> Reviewed-by: Christian König 
> ---
>   drivers/gpu/drm/scheduler/sched_main.c | 11 +--
>   1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/scheduler/sched_main.c 
> b/drivers/gpu/drm/scheduler/sched_main.c
> index 7816de7..03e6bd8 100644
> --- a/drivers/gpu/drm/scheduler/sched_main.c
> +++ b/drivers/gpu/drm/scheduler/sched_main.c
> @@ -375,8 +375,6 @@ void drm_sched_stop(struct drm_gpu_scheduler *sched, 
> struct drm_sched_job *bad)
>   if (s_job->s_fence->parent &&
>   dma_fence_remove_callback(s_job->s_fence->parent,
> &s_job->cb)) {
> - dma_fence_put(s_job->s_fence->parent);
> - s_job->s_fence->parent = NULL;

I vaguely remember Monk set parent to be NULL to avoiod potiential free 
problem after callback removal.


-David


>   atomic_dec(&sched->hw_rq_count);
>   } else {
>   /*
> @@ -403,6 +401,14 @@ void drm_sched_stop(struct drm_gpu_scheduler *sched, 
> struct drm_sched_job *bad)
>   sched->ops->free_job(s_job);
>   }
>   }
> +
> + /*
> +  * Stop pending timer in flight as we rearm it in  drm_sched_start. This
> +  * avoids the pending timeout work in progress to fire right away after
> +  * this TDR finished and before the newly restarted jobs had a
> +  * chance to complete.
> +  */
> + cancel_delayed_work(&sched->work_tdr);
>   }
>   
>   EXPORT_SYMBOL(drm_sched_stop);
> @@ -477,6 +483,7 @@ void drm_sched_resubmit_jobs(struct drm_gpu_scheduler 
> *sched)
>   if (found_guilty && s_job->s_fence->scheduled.context == 
> guilty_context)
>   dma_fence_set_error(&s_fence->finished, -ECANCELED);
>   
> + dma_fence_put(s_job->s_fence->parent);
>   s_job->s_fence->parent = sched->ops->run_job(s_job);
>   }
>   }
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Re: [PATCH v5 3/6] drm/scheduler: rework job destruction

2019-04-22 Thread Chunming Zhou
Hi Andrey,

static void drm_sched_process_job(struct dma_fence *f, struct 
dma_fence_cb *cb)
{
...
     spin_lock_irqsave(&sched->job_list_lock, flags);
     /* remove job from ring_mirror_list */
     list_del_init(&s_job->node);
     spin_unlock_irqrestore(&sched->job_list_lock, flags);
[David] How about just remove above to worker from irq process? Any 
problem? Maybe I missed previous your discussion, but I think removing 
lock for list is a risk for future maintenance although you make sure 
thread safe currently.

-David

...

     schedule_work(&s_job->finish_work);
}

在 2019/4/18 23:00, Andrey Grodzovsky 写道:
> From: Christian König 
>
> We now destroy finished jobs from the worker thread to make sure that
> we never destroy a job currently in timeout processing.
> By this we avoid holding lock around ring mirror list in drm_sched_stop
> which should solve a deadlock reported by a user.
>
> v2: Remove unused variable.
> v4: Move guilty job free into sched code.
> v5:
> Move sched->hw_rq_count to drm_sched_start to account for counter
> decrement in drm_sched_stop even when we don't call resubmit jobs
> if guily job did signal.
>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=109692
>
> Signed-off-by: Christian König 
> Signed-off-by: Andrey Grodzovsky 
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |   9 +-
>   drivers/gpu/drm/etnaviv/etnaviv_dump.c |   4 -
>   drivers/gpu/drm/etnaviv/etnaviv_sched.c|   2 +-
>   drivers/gpu/drm/lima/lima_sched.c  |   2 +-
>   drivers/gpu/drm/panfrost/panfrost_job.c|   2 +-
>   drivers/gpu/drm/scheduler/sched_main.c | 159 
> +
>   drivers/gpu/drm/v3d/v3d_sched.c|   2 +-
>   include/drm/gpu_scheduler.h|   6 +-
>   8 files changed, 102 insertions(+), 84 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index 7cee269..a0e165c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -3334,7 +3334,7 @@ static int amdgpu_device_pre_asic_reset(struct 
> amdgpu_device *adev,
>   if (!ring || !ring->sched.thread)
>   continue;
>   
> - drm_sched_stop(&ring->sched);
> + drm_sched_stop(&ring->sched, &job->base);
>   
>   /* after all hw jobs are reset, hw fence is meaningless, so 
> force_completion */
>   amdgpu_fence_driver_force_completion(ring);
> @@ -3343,8 +3343,6 @@ static int amdgpu_device_pre_asic_reset(struct 
> amdgpu_device *adev,
>   if(job)
>   drm_sched_increase_karma(&job->base);
>   
> -
> -
>   if (!amdgpu_sriov_vf(adev)) {
>   
>   if (!need_full_reset)
> @@ -3482,8 +3480,7 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info 
> *hive,
>   return r;
>   }
>   
> -static void amdgpu_device_post_asic_reset(struct amdgpu_device *adev,
> -   struct amdgpu_job *job)
> +static void amdgpu_device_post_asic_reset(struct amdgpu_device *adev)
>   {
>   int i;
>   
> @@ -3623,7 +3620,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device 
> *adev,
>   
>   /* Post ASIC reset for all devs .*/
>   list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
> - amdgpu_device_post_asic_reset(tmp_adev, tmp_adev == adev ? job 
> : NULL);
> + amdgpu_device_post_asic_reset(tmp_adev);
>   
>   if (r) {
>   /* bad news, how to tell it to userspace ? */
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c 
> b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
> index 33854c9..5778d9c 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_dump.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
> @@ -135,13 +135,11 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu)
>   mmu_size + gpu->buffer.size;
>   
>   /* Add in the active command buffers */
> - spin_lock_irqsave(&gpu->sched.job_list_lock, flags);
>   list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) {
>   submit = to_etnaviv_submit(s_job);
>   file_size += submit->cmdbuf.size;
>   n_obj++;
>   }
> - spin_unlock_irqrestore(&gpu->sched.job_list_lock, flags);
>   
>   /* Add in the active buffer objects */
>   list_for_each_entry(vram, &gpu->mmu->mappings, mmu_node) {
> @@ -183,14 +181,12 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu)
> gpu->buffer.size,
> etnaviv_cmdbuf_get_va(&gpu->buffer));
>   
> - spin_lock_irqsave(&gpu->sched.job_list_lock, flags);
>   list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) {
>   submit = to_etnaviv_submit(s_job);
>   etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD,
> submit->cmdbuf.vaddr, submit->cmdbuf.size,
> 

Re: [PATCH v5 6/6] drm/amdgpu: Avoid HW reset if guilty job already signaled.

2019-04-22 Thread Grodzovsky, Andrey
Ping for patches 3, new patch 5 and patch 6.

Andrey

On 4/18/19 11:00 AM, Andrey Grodzovsky wrote:
> Also reject TDRs if another one already running.
>
> v2:
> Stop all schedulers across device and entire XGMI hive before
> force signaling HW fences.
> Avoid passing job_signaled to helper fnctions to keep all the decision
> making about skipping HW reset in one place.
>
> v3:
> Fix SW sched. hang after non HW reset. sched.hw_rq_count has to be balanced
> against it's decrement in drm_sched_stop in non HW reset case.
> v4: rebase
> v5: Revert v3 as we do it now in sceduler code.
>
> Signed-off-by: Andrey Grodzovsky 
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 143 
> +++--
>   1 file changed, 95 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index a0e165c..85f8792 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -3334,8 +3334,6 @@ static int amdgpu_device_pre_asic_reset(struct 
> amdgpu_device *adev,
>   if (!ring || !ring->sched.thread)
>   continue;
>   
> - drm_sched_stop(&ring->sched, &job->base);
> -
>   /* after all hw jobs are reset, hw fence is meaningless, so 
> force_completion */
>   amdgpu_fence_driver_force_completion(ring);
>   }
> @@ -3343,6 +3341,7 @@ static int amdgpu_device_pre_asic_reset(struct 
> amdgpu_device *adev,
>   if(job)
>   drm_sched_increase_karma(&job->base);
>   
> + /* Don't suspend on bare metal if we are not going to HW reset the ASIC 
> */
>   if (!amdgpu_sriov_vf(adev)) {
>   
>   if (!need_full_reset)
> @@ -3480,37 +3479,21 @@ static int amdgpu_do_asic_reset(struct 
> amdgpu_hive_info *hive,
>   return r;
>   }
>   
> -static void amdgpu_device_post_asic_reset(struct amdgpu_device *adev)
> +static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, bool trylock)
>   {
> - int i;
> -
> - for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
> - struct amdgpu_ring *ring = adev->rings[i];
> -
> - if (!ring || !ring->sched.thread)
> - continue;
> -
> - if (!adev->asic_reset_res)
> - drm_sched_resubmit_jobs(&ring->sched);
> + if (trylock) {
> + if (!mutex_trylock(&adev->lock_reset))
> + return false;
> + } else
> + mutex_lock(&adev->lock_reset);
>   
> - drm_sched_start(&ring->sched, !adev->asic_reset_res);
> - }
> -
> - if (!amdgpu_device_has_dc_support(adev)) {
> - drm_helper_resume_force_mode(adev->ddev);
> - }
> -
> - adev->asic_reset_res = 0;
> -}
> -
> -static void amdgpu_device_lock_adev(struct amdgpu_device *adev)
> -{
> - mutex_lock(&adev->lock_reset);
>   atomic_inc(&adev->gpu_reset_counter);
>   adev->in_gpu_reset = 1;
>   /* Block kfd: SRIOV would do it separately */
>   if (!amdgpu_sriov_vf(adev))
>   amdgpu_amdkfd_pre_reset(adev);
> +
> + return true;
>   }
>   
>   static void amdgpu_device_unlock_adev(struct amdgpu_device *adev)
> @@ -3538,40 +3521,42 @@ static void amdgpu_device_unlock_adev(struct 
> amdgpu_device *adev)
>   int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
> struct amdgpu_job *job)
>   {
> - int r;
> + struct list_head device_list, *device_list_handle =  NULL;
> + bool need_full_reset, job_signaled;
>   struct amdgpu_hive_info *hive = NULL;
> - bool need_full_reset = false;
>   struct amdgpu_device *tmp_adev = NULL;
> - struct list_head device_list, *device_list_handle =  NULL;
> + int i, r = 0;
>   
> + need_full_reset = job_signaled = false;
>   INIT_LIST_HEAD(&device_list);
>   
>   dev_info(adev->dev, "GPU reset begin!\n");
>   
> + hive = amdgpu_get_xgmi_hive(adev, false);
> +
>   /*
> -  * In case of XGMI hive disallow concurrent resets to be triggered
> -  * by different nodes. No point also since the one node already 
> executing
> -  * reset will also reset all the other nodes in the hive.
> +  * Here we trylock to avoid chain of resets executing from
> +  * either trigger by jobs on different adevs in XGMI hive or jobs on
> +  * different schedulers for same device while this TO handler is 
> running.
> +  * We always reset all schedulers for device and all devices for XGMI
> +  * hive so that should take care of them too.
>*/
> - hive = amdgpu_get_xgmi_hive(adev, 0);
> - if (hive && adev->gmc.xgmi.num_physical_nodes > 1 &&
> - !mutex_trylock(&hive->reset_lock))
> +
> + if (hive && !mutex_trylock(&hive->reset_lock)) {
> + DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another 
> already in progress",
> +  job->base.id, hive->hive_id);
>  

RE: [PATCH] drm/amd/powerplay: enable UMDPSTATE support on raven2

2019-04-22 Thread Huang, Ray
> -Original Message-
> From: amd-gfx [mailto:amd-gfx-boun...@lists.freedesktop.org] On Behalf
> Of Chengming Gui
> Sent: Monday, April 22, 2019 5:05 PM
> To: amd-gfx@lists.freedesktop.org
> Cc: Gui, Jack 
> Subject: [PATCH] drm/amd/powerplay: enable UMDPSTATE support on
> raven2
> 

Please describe this patch here, and don't leave it empty.
With that fixed, please add
Reviewed-by: Huang Rui 

> Signed-off-by: Chengming Gui 
> ---
>  drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c | 5 -
>  1 file changed, 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
> b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
> index b508b72..c2fa6bc 100644
> --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
> +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
> @@ -582,11 +582,6 @@ static int smu10_dpm_force_dpm_level(struct
> pp_hwmgr *hwmgr,
>   return 0;
>   }
> 
> - /* Disable UMDPSTATE support on rv2 temporarily */
> - if ((adev->asic_type == CHIP_RAVEN) &&
> - (adev->rev_id >= 8))
> - return 0;
> -
>   if (min_sclk < data->gfx_min_freq_limit)
>   min_sclk = data->gfx_min_freq_limit;
> 
> --
> 2.7.4
> 
> ___
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

RE: [PATCH] drm/amd/powerplay: add set/get_power_profile_mode for Raven

2019-04-22 Thread Huang, Ray
> -Original Message-
> From: amd-gfx [mailto:amd-gfx-boun...@lists.freedesktop.org] On Behalf
> Of Chengming Gui
> Sent: Monday, April 22, 2019 4:03 PM
> To: amd-gfx@lists.freedesktop.org
> Cc: Gui, Jack 
> Subject: [PATCH] drm/amd/powerplay: add set/get_power_profile_mode
> for Raven

Please add the commit description here. 
Patch looks good for me, with that fix, please add
Reviewed-by: Huang Rui 

> 
> Signed-off-by: Chengming Gui 
> ---
>  drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c | 92
> +++
>  drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h  |  1 -
>  drivers/gpu/drm/amd/powerplay/inc/smu10.h | 14 ++--
>  3 files changed, 100 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
> b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
> index f32e3d0..ee25ba1 100644
> --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
> +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
> @@ -35,6 +35,7 @@
>  #include "smu10_hwmgr.h"
>  #include "power_state.h"
>  #include "soc15_common.h"
> +#include "smu10.h"
> 
>  #define SMU10_MAX_DEEPSLEEP_DIVIDER_ID 5
>  #define SMU10_MINIMUM_ENGINE_CLOCK 800   /* 8Mhz, the low
> boundary of engine clock allowed on this chip */
> @@ -1200,6 +1201,95 @@ static void smu10_powergate_vcn(struct
> pp_hwmgr *hwmgr, bool bgate)
>   }
>  }
> 
> +static int conv_power_profile_to_pplib_workload(int power_profile) {
> + int pplib_workload = 0;
> +
> + switch (power_profile) {
> + case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT:
> + pplib_workload = WORKLOAD_DEFAULT_BIT;
> + break;
> + case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
> + pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
> + break;
> + case PP_SMC_POWER_PROFILE_POWERSAVING:
> + pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT;
> + break;
> + case PP_SMC_POWER_PROFILE_VIDEO:
> + pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT;
> + break;
> + case PP_SMC_POWER_PROFILE_VR:
> + pplib_workload = WORKLOAD_PPLIB_VR_BIT;
> + break;
> + case PP_SMC_POWER_PROFILE_COMPUTE:
> + pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT;
> + break;
> + }
> +
> + return pplib_workload;
> +}
> +
> +static int smu10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char
> +*buf) {
> + uint32_t i, size = 0;
> + static const uint8_t
> + profile_mode_setting[6][4] = {{70, 60, 0, 0,},
> + {70, 60, 1, 3,},
> + {90, 60, 0, 0,},
> + {70, 60, 0, 0,},
> + {70, 90, 0, 0,},
> + {30, 60, 0, 6,},
> + };
> + static const char *profile_name[6] = {
> + "BOOTUP_DEFAULT",
> + "3D_FULL_SCREEN",
> + "POWER_SAVING",
> + "VIDEO",
> + "VR",
> + "COMPUTE"};
> + static const char *title[6] = {"NUM",
> + "MODE_NAME",
> + "BUSY_SET_POINT",
> + "FPS",
> + "USE_RLC_BUSY",
> + "MIN_ACTIVE_LEVEL"};
> +
> + if (!buf)
> + return -EINVAL;
> +
> + size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0],
> + title[1], title[2], title[3], title[4], title[5]);
> +
> + for (i = 0; i <= PP_SMC_POWER_PROFILE_COMPUTE; i++)
> + size += sprintf(buf + size,
> "%3d %14s%s: %14d %3d %10d %14d\n",
> + i, profile_name[i], (i == hwmgr-
> >power_profile_mode) ? "*" : " ",
> + profile_mode_setting[i][0],
> profile_mode_setting[i][1],
> + profile_mode_setting[i][2],
> profile_mode_setting[i][3]);
> +
> + return size;
> +}
> +
> +static int smu10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long
> +*input, uint32_t size) {
> + int workload_type = 0;
> +
> + hwmgr->power_profile_mode = input[size];
> +
> + if (hwmgr->power_profile_mode >
> PP_SMC_POWER_PROFILE_COMPUTE) {
> + pr_err("Invalid power profile mode %d\n", hwmgr-
> >power_profile_mode);
> + return -EINVAL;
> + }
> +
> + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
> + workload_type =
> + conv_power_profile_to_pplib_workload(hwmgr-
> >power_profile_mode);
> + smum_send_msg_to_smc_with_parameter(hwmgr,
> PPSMC_MSG_ActiveProcessNotify,
> + 1 << workload_type);
> +
> + return 0;
> +}
> +
> +
>  static const struct pp_hwmgr_func smu10_hwmgr_fun

RE: [PATCH] drm/amdgpu: Check if smu.ppt_funcs is initialized before accessing

2019-04-22 Thread Huang, Ray
> -Original Message-
> From: amd-gfx [mailto:amd-gfx-boun...@lists.freedesktop.org] On Behalf
> Of Alex Deucher
> Sent: Friday, April 19, 2019 10:26 PM
> To: Li, Sun peng (Leo) 
> Cc: Gui, Jack ; amd-gfx list  g...@lists.freedesktop.org>
> Subject: Re: [PATCH] drm/amdgpu: Check if smu.ppt_funcs is initialized
> before accessing
> 
> On Thu, Apr 18, 2019 at 12:01 PM  wrote:
> >
> > From: Leo Li 
> >
> > smu.ppt_funcs is only initialized for specific SMU versions.
> >
> > On a Hawaii ASIC, attempting to access the udev attribute
> > ATTRS{power_dpm_state} will cause a null pointer deref in
> > amdgpu_get_dpm_state() because of this.
> >
> > Fix by checking that ppt_funcs is initialized first.
> >
> > CC: Chengming Gui 
> > Signed-off-by: Leo Li 
> > ---
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > index 4b7a076..7993623 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> > @@ -144,7 +144,7 @@ static ssize_t amdgpu_get_dpm_state(struct device
> *dev,
> > struct amdgpu_device *adev = ddev->dev_private;
> > enum amd_pm_state_type pm;
> >
> > -   if (adev->smu.ppt_funcs->get_current_power_state)
> > +   if (adev->smu.ppt_funcs && adev->smu.ppt_funcs-
> >get_current_power_state)
> 
> For consistency, I think we probably want something like:
> if (is_support_sw_smu(adev) && adev->smu.ppt_funcs-
> >get_current_power_state)
> 
> Either way:
> Reviewed-by: Alex Deucher 

Yes. The same comment with me. Please use is_support_sw_smu() to check it.
With that fixed, please add Reviewed-by: Huang Rui 

> 
> > pm = amdgpu_smu_get_current_power_state(adev);
> > else if (adev->powerplay.pp_funcs->get_current_power_state)
> > pm = amdgpu_dpm_get_current_power_state(adev);
> > --
> > 2.7.4
> >
> > ___
> > amd-gfx mailing list
> > amd-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/amd-gfx
> ___
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/powerplay: enable UMDPSTATE support on raven2

2019-04-22 Thread Chengming Gui
Signed-off-by: Chengming Gui 
---
 drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
index b508b72..c2fa6bc 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
@@ -582,11 +582,6 @@ static int smu10_dpm_force_dpm_level(struct pp_hwmgr 
*hwmgr,
return 0;
}
 
-   /* Disable UMDPSTATE support on rv2 temporarily */
-   if ((adev->asic_type == CHIP_RAVEN) &&
-   (adev->rev_id >= 8))
-   return 0;
-
if (min_sclk < data->gfx_min_freq_limit)
min_sclk = data->gfx_min_freq_limit;
 
-- 
2.7.4

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

RE: [PATCH] drm/amd/powerplay: add set/get_power_profile_mode for Raven

2019-04-22 Thread Quan, Evan


> -Original Message-
> From: amd-gfx  On Behalf Of
> Chengming Gui
> Sent: 2019年4月22日 16:03
> To: amd-gfx@lists.freedesktop.org
> Cc: Gui, Jack 
> Subject: [PATCH] drm/amd/powerplay: add set/get_power_profile_mode
> for Raven
> 
> Signed-off-by: Chengming Gui 
> ---
>  drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c | 92
> +++
>  drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h  |  1 -
>  drivers/gpu/drm/amd/powerplay/inc/smu10.h | 14 ++--
>  3 files changed, 100 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
> b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
> index f32e3d0..ee25ba1 100644
> --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
> +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
> @@ -35,6 +35,7 @@
>  #include "smu10_hwmgr.h"
>  #include "power_state.h"
>  #include "soc15_common.h"
> +#include "smu10.h"
> 
>  #define SMU10_MAX_DEEPSLEEP_DIVIDER_ID 5
>  #define SMU10_MINIMUM_ENGINE_CLOCK 800   /* 8Mhz, the low
> boundary of engine clock allowed on this chip */
> @@ -1200,6 +1201,95 @@ static void smu10_powergate_vcn(struct
> pp_hwmgr *hwmgr, bool bgate)
>   }
>  }
> 
> +static int conv_power_profile_to_pplib_workload(int power_profile) {
> + int pplib_workload = 0;
> +
> + switch (power_profile) {
> + case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT:
> + pplib_workload = WORKLOAD_DEFAULT_BIT;
> + break;
> + case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
> + pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
> + break;
> + case PP_SMC_POWER_PROFILE_POWERSAVING:
> + pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT;
> + break;
> + case PP_SMC_POWER_PROFILE_VIDEO:
> + pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT;
> + break;
> + case PP_SMC_POWER_PROFILE_VR:
> + pplib_workload = WORKLOAD_PPLIB_VR_BIT;
> + break;
> + case PP_SMC_POWER_PROFILE_COMPUTE:
> + pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT;
> + break;
> + }
> +
> + return pplib_workload;
> +}
> +
> +static int smu10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char
> +*buf) {
> + uint32_t i, size = 0;
> + static const uint8_t
> + profile_mode_setting[6][4] = {{70, 60, 0, 0,},
> + {70, 60, 1, 3,},
> + {90, 60, 0, 0,},
> + {70, 60, 0, 0,},
> + {70, 90, 0, 0,},
> + {30, 60, 0, 6,},
> + };
> + static const char *profile_name[6] = {
> + "BOOTUP_DEFAULT",
> + "3D_FULL_SCREEN",
> + "POWER_SAVING",
> + "VIDEO",
> + "VR",
> + "COMPUTE"};
> + static const char *title[6] = {"NUM",
> + "MODE_NAME",
> + "BUSY_SET_POINT",
> + "FPS",
> + "USE_RLC_BUSY",
> + "MIN_ACTIVE_LEVEL"};
> +
> + if (!buf)
> + return -EINVAL;
> +
> + size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0],
> + title[1], title[2], title[3], title[4], title[5]);
> +
> + for (i = 0; i <= PP_SMC_POWER_PROFILE_COMPUTE; i++)
> + size += sprintf(buf + size,
> "%3d %14s%s: %14d %3d %10d %14d\n",
> + i, profile_name[i], (i == hwmgr-
> >power_profile_mode) ? "*" : " ",
> + profile_mode_setting[i][0],
> profile_mode_setting[i][1],
> + profile_mode_setting[i][2],
> profile_mode_setting[i][3]);
> +
> + return size;
> +}
> +
> +static int smu10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long
> +*input, uint32_t size) {
> + int workload_type = 0;
> +
> + hwmgr->power_profile_mode = input[size];
> +
> + if (hwmgr->power_profile_mode >
> PP_SMC_POWER_PROFILE_COMPUTE) {
> + pr_err("Invalid power profile mode %d\n", hwmgr-
> >power_profile_mode);
> + return -EINVAL;
> + }
[Quan, Evan] check invalid input before changing hwmgr->power_profile_mode. 
With that fixed, reviewed-by: Evan Quan 
> +
> + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
> + workload_type =
> + conv_power_profile_to_pplib_workload(hwmgr-
> >power_profile_mode);
> + smum_send_msg_to_smc_with_parameter(hwmgr,
> PPSMC_MSG_ActiveProcessNotify,
> + 1 << workload_type);
> +
> + return 0;
> +}
> +
> +
>  static const struct pp_hwmgr_func smu10_hwmgr_funcs = {
>   .backend_init = smu10_hwmgr_backend_init,
>

[PATCH] drm/amd/powerplay: add set/get_power_profile_mode for Raven

2019-04-22 Thread Chengming Gui
Signed-off-by: Chengming Gui 
---
 drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c | 92 +++
 drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h  |  1 -
 drivers/gpu/drm/amd/powerplay/inc/smu10.h | 14 ++--
 3 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
index f32e3d0..ee25ba1 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
@@ -35,6 +35,7 @@
 #include "smu10_hwmgr.h"
 #include "power_state.h"
 #include "soc15_common.h"
+#include "smu10.h"
 
 #define SMU10_MAX_DEEPSLEEP_DIVIDER_ID 5
 #define SMU10_MINIMUM_ENGINE_CLOCK 800   /* 8Mhz, the low boundary of 
engine clock allowed on this chip */
@@ -1200,6 +1201,95 @@ static void smu10_powergate_vcn(struct pp_hwmgr *hwmgr, 
bool bgate)
}
 }
 
+static int conv_power_profile_to_pplib_workload(int power_profile)
+{
+   int pplib_workload = 0;
+
+   switch (power_profile) {
+   case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT:
+   pplib_workload = WORKLOAD_DEFAULT_BIT;
+   break;
+   case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
+   pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
+   break;
+   case PP_SMC_POWER_PROFILE_POWERSAVING:
+   pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT;
+   break;
+   case PP_SMC_POWER_PROFILE_VIDEO:
+   pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT;
+   break;
+   case PP_SMC_POWER_PROFILE_VR:
+   pplib_workload = WORKLOAD_PPLIB_VR_BIT;
+   break;
+   case PP_SMC_POWER_PROFILE_COMPUTE:
+   pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT;
+   break;
+   }
+
+   return pplib_workload;
+}
+
+static int smu10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
+{
+   uint32_t i, size = 0;
+   static const uint8_t
+   profile_mode_setting[6][4] = {{70, 60, 0, 0,},
+   {70, 60, 1, 3,},
+   {90, 60, 0, 0,},
+   {70, 60, 0, 0,},
+   {70, 90, 0, 0,},
+   {30, 60, 0, 6,},
+   };
+   static const char *profile_name[6] = {
+   "BOOTUP_DEFAULT",
+   "3D_FULL_SCREEN",
+   "POWER_SAVING",
+   "VIDEO",
+   "VR",
+   "COMPUTE"};
+   static const char *title[6] = {"NUM",
+   "MODE_NAME",
+   "BUSY_SET_POINT",
+   "FPS",
+   "USE_RLC_BUSY",
+   "MIN_ACTIVE_LEVEL"};
+
+   if (!buf)
+   return -EINVAL;
+
+   size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0],
+   title[1], title[2], title[3], title[4], title[5]);
+
+   for (i = 0; i <= PP_SMC_POWER_PROFILE_COMPUTE; i++)
+   size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n",
+   i, profile_name[i], (i == hwmgr->power_profile_mode) ? 
"*" : " ",
+   profile_mode_setting[i][0], profile_mode_setting[i][1],
+   profile_mode_setting[i][2], profile_mode_setting[i][3]);
+
+   return size;
+}
+
+static int smu10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, 
uint32_t size)
+{
+   int workload_type = 0;
+
+   hwmgr->power_profile_mode = input[size];
+
+   if (hwmgr->power_profile_mode > PP_SMC_POWER_PROFILE_COMPUTE) {
+   pr_err("Invalid power profile mode %d\n", 
hwmgr->power_profile_mode);
+   return -EINVAL;
+   }
+
+   /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
+   workload_type =
+   conv_power_profile_to_pplib_workload(hwmgr->power_profile_mode);
+   smum_send_msg_to_smc_with_parameter(hwmgr, 
PPSMC_MSG_ActiveProcessNotify,
+   1 << workload_type);
+
+   return 0;
+}
+
+
 static const struct pp_hwmgr_func smu10_hwmgr_funcs = {
.backend_init = smu10_hwmgr_backend_init,
.backend_fini = smu10_hwmgr_backend_fini,
@@ -1241,6 +1331,8 @@ static const struct pp_hwmgr_func smu10_hwmgr_funcs = {
.powergate_sdma = smu10_powergate_sdma,
.set_hard_min_dcefclk_by_freq = smu10_set_hard_min_dcefclk_by_freq,
.set_hard_min_fclk_by_freq = smu10_set_hard_min_fclk_by_freq,
+   .get_power_profile_mode = smu10_get_power_profile_mode,
+   .set_power_profile_mode = smu10_set_power_profile_mode,
 };
 
 int smu1