amd-gfx.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] drm/amdkfd: Cleanup IO links during KFD device removal
@ 2022-04-07 16:15 Mukul Joshi
  2022-04-07 17:05 ` Andrey Grodzovsky
  2022-04-12  0:16 ` Felix Kuehling
  0 siblings, 2 replies; 5+ messages in thread
From: Mukul Joshi @ 2022-04-07 16:15 UTC (permalink / raw)
  To: amd-gfx; +Cc: Mukul Joshi, Felix.Kuehling, Shuotao Xu

Currently, the IO-links to the device being removed from topology,
are not cleared. As a result, there would be dangling links left in
the KFD topology. This patch aims to fix the following:
1. Cleanup all IO links to the device being removed.
2. Ensure that node numbering in sysfs and nodes proximity domain
   values are consistent after the device is removed:
   a. Adding a device and removing a GPU device are made mutually
      exclusive.
   b. The global proximity domain counter is no longer required to be
      an atomic counter. A normal 32-bit counter can be used instead.
3. Update generation_count to let user-mode know that topology has
   changed due to device removal.

CC: Shuotao Xu <shuotaoxu@microsoft.com>
Signed-off-by: Mukul Joshi <mukul.joshi@amd.com>
---
 drivers/gpu/drm/amd/amdkfd/kfd_crat.c     |  4 +-
 drivers/gpu/drm/amd/amdkfd/kfd_priv.h     |  2 +
 drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 79 ++++++++++++++++++++---
 3 files changed, 74 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index 1eaabd2cb41b..afc8a7fcdad8 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -1056,7 +1056,7 @@ static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink,
 	 * table, add corresponded reversed direction link now.
 	 */
 	if (props && (iolink->flags & CRAT_IOLINK_FLAGS_BI_DIRECTIONAL)) {
-		to_dev = kfd_topology_device_by_proximity_domain(id_to);
+		to_dev = kfd_topology_device_by_proximity_domain_no_lock(id_to);
 		if (!to_dev)
 			return -ENODEV;
 		/* same everything but the other direction */
@@ -2225,7 +2225,7 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
 	 */
 	if (kdev->hive_id) {
 		for (nid = 0; nid < proximity_domain; ++nid) {
-			peer_dev = kfd_topology_device_by_proximity_domain(nid);
+			peer_dev = kfd_topology_device_by_proximity_domain_no_lock(nid);
 			if (!peer_dev->gpu)
 				continue;
 			if (peer_dev->gpu->hive_id != kdev->hive_id)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index e1b7e6afa920..8a43def1f638 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -1016,6 +1016,8 @@ int kfd_topology_add_device(struct kfd_dev *gpu);
 int kfd_topology_remove_device(struct kfd_dev *gpu);
 struct kfd_topology_device *kfd_topology_device_by_proximity_domain(
 						uint32_t proximity_domain);
+struct kfd_topology_device *kfd_topology_device_by_proximity_domain_no_lock(
+						uint32_t proximity_domain);
 struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id);
 struct kfd_dev *kfd_device_by_id(uint32_t gpu_id);
 struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index 3bdcae239bc0..874a273b81f7 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -46,27 +46,38 @@ static struct list_head topology_device_list;
 static struct kfd_system_properties sys_props;
 
 static DECLARE_RWSEM(topology_lock);
-static atomic_t topology_crat_proximity_domain;
+static uint32_t topology_crat_proximity_domain;
 
-struct kfd_topology_device *kfd_topology_device_by_proximity_domain(
+struct kfd_topology_device *kfd_topology_device_by_proximity_domain_no_lock(
 						uint32_t proximity_domain)
 {
 	struct kfd_topology_device *top_dev;
 	struct kfd_topology_device *device = NULL;
 
-	down_read(&topology_lock);
-
 	list_for_each_entry(top_dev, &topology_device_list, list)
 		if (top_dev->proximity_domain == proximity_domain) {
 			device = top_dev;
 			break;
 		}
 
+	return device;
+}
+
+struct kfd_topology_device *kfd_topology_device_by_proximity_domain(
+						uint32_t proximity_domain)
+{
+	struct kfd_topology_device *device = NULL;
+
+	down_read(&topology_lock);
+
+	device = kfd_topology_device_by_proximity_domain_no_lock(
+							proximity_domain);
 	up_read(&topology_lock);
 
 	return device;
 }
 
+
 struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id)
 {
 	struct kfd_topology_device *top_dev = NULL;
@@ -1060,7 +1071,7 @@ int kfd_topology_init(void)
 	down_write(&topology_lock);
 	kfd_topology_update_device_list(&temp_topology_device_list,
 					&topology_device_list);
-	atomic_set(&topology_crat_proximity_domain, sys_props.num_devices-1);
+	topology_crat_proximity_domain = sys_props.num_devices-1;
 	ret = kfd_topology_update_sysfs();
 	up_write(&topology_lock);
 
@@ -1295,8 +1306,6 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
 
 	pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id);
 
-	proximity_domain = atomic_inc_return(&topology_crat_proximity_domain);
-
 	/* Include the CPU in xGMI hive if xGMI connected by assigning it the hive ID. */
 	if (gpu->hive_id && gpu->adev->gmc.xgmi.connected_to_cpu) {
 		struct kfd_topology_device *top_dev;
@@ -1321,12 +1330,16 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
 	 */
 	dev = kfd_assign_gpu(gpu);
 	if (!dev) {
+		down_write(&topology_lock);
+		proximity_domain = ++topology_crat_proximity_domain;
+
 		res = kfd_create_crat_image_virtual(&crat_image, &image_size,
 						    COMPUTE_UNIT_GPU, gpu,
 						    proximity_domain);
 		if (res) {
 			pr_err("Error creating VCRAT for GPU (ID: 0x%x)\n",
 			       gpu_id);
+			topology_crat_proximity_domain--;
 			return res;
 		}
 		res = kfd_parse_crat_table(crat_image,
@@ -1335,10 +1348,10 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
 		if (res) {
 			pr_err("Error parsing VCRAT for GPU (ID: 0x%x)\n",
 			       gpu_id);
+			topology_crat_proximity_domain--;
 			goto err;
 		}
 
-		down_write(&topology_lock);
 		kfd_topology_update_device_list(&temp_topology_device_list,
 			&topology_device_list);
 
@@ -1485,25 +1498,73 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
 	return res;
 }
 
+static void kfd_topology_update_io_links(int proximity_domain)
+{
+	struct kfd_topology_device *dev;
+	struct kfd_iolink_properties *iolink, *p2plink, *tmp;
+	/*
+	 * The topology list currently is arranged in increasing
+	 * order of proximity domain.
+	 *
+	 * Two things need to be done when a device is removed:
+	 * 1. All the IO links to this device need to be
+	 *    removed.
+	 * 2. All nodes after the current device node need to move
+	 *    up once this device node is removed from the topology
+	 *    list. As a result, the proximity domain values for
+	 *    all nodes after the node being deleted reduce by 1.
+	 *    This would also cause the proximity domain values for
+	 *    io links to be updated based on new proximity
+	 *    domain values.
+	 */
+	list_for_each_entry(dev, &topology_device_list, list) {
+		if (dev->proximity_domain > proximity_domain)
+			dev->proximity_domain--;
+
+		list_for_each_entry_safe(iolink, tmp, &dev->io_link_props, list) {
+			/*
+			 * If there is an io link to the dev being deleted
+			 * then remove that IO link also.
+			 */
+			if (iolink->node_to == proximity_domain) {
+				list_del(&iolink->list);
+				dev->io_link_count--;
+				dev->node_props.io_links_count--;
+			} else if (iolink->node_from > proximity_domain) {
+				iolink->node_from--;
+			} else if (iolink->node_to > proximity_domain) {
+				iolink->node_to--;
+			}
+		}
+
+	}
+}
+
 int kfd_topology_remove_device(struct kfd_dev *gpu)
 {
 	struct kfd_topology_device *dev, *tmp;
 	uint32_t gpu_id;
 	int res = -ENODEV;
+	int i = 0;
 
 	down_write(&topology_lock);
 
-	list_for_each_entry_safe(dev, tmp, &topology_device_list, list)
+	list_for_each_entry_safe(dev, tmp, &topology_device_list, list) {
 		if (dev->gpu == gpu) {
 			gpu_id = dev->gpu_id;
 			kfd_remove_sysfs_node_entry(dev);
 			kfd_release_topology_device(dev);
 			sys_props.num_devices--;
+			kfd_topology_update_io_links(i);
+			topology_crat_proximity_domain = sys_props.num_devices-1;
+			sys_props.generation_count++;
 			res = 0;
 			if (kfd_topology_update_sysfs() < 0)
 				kfd_topology_release_sysfs();
 			break;
 		}
+		i++;
+	}
 
 	up_write(&topology_lock);
 
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] drm/amdkfd: Cleanup IO links during KFD device removal
  2022-04-07 16:15 [PATCH] drm/amdkfd: Cleanup IO links during KFD device removal Mukul Joshi
@ 2022-04-07 17:05 ` Andrey Grodzovsky
  2022-04-12  0:16 ` Felix Kuehling
  1 sibling, 0 replies; 5+ messages in thread
From: Andrey Grodzovsky @ 2022-04-07 17:05 UTC (permalink / raw)
  To: Mukul Joshi, amd-gfx; +Cc: Felix.Kuehling, Shuotao Xu

I suggest adding another patch to handle unbalanced decrement of
kfd_lock in kgd2kfd_suspend. This patch alone is not enough to fix
all removal issues.

Andrey

On 2022-04-07 12:15, Mukul Joshi wrote:
> Currently, the IO-links to the device being removed from topology,
> are not cleared. As a result, there would be dangling links left in
> the KFD topology. This patch aims to fix the following:
> 1. Cleanup all IO links to the device being removed.
> 2. Ensure that node numbering in sysfs and nodes proximity domain
>     values are consistent after the device is removed:
>     a. Adding a device and removing a GPU device are made mutually
>        exclusive.
>     b. The global proximity domain counter is no longer required to be
>        an atomic counter. A normal 32-bit counter can be used instead.
> 3. Update generation_count to let user-mode know that topology has
>     changed due to device removal.
> 
> CC: Shuotao Xu <shuotaoxu@microsoft.com>
> Signed-off-by: Mukul Joshi <mukul.joshi@amd.com>
> ---
>   drivers/gpu/drm/amd/amdkfd/kfd_crat.c     |  4 +-
>   drivers/gpu/drm/amd/amdkfd/kfd_priv.h     |  2 +
>   drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 79 ++++++++++++++++++++---
>   3 files changed, 74 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
> index 1eaabd2cb41b..afc8a7fcdad8 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
> @@ -1056,7 +1056,7 @@ static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink,
>   	 * table, add corresponded reversed direction link now.
>   	 */
>   	if (props && (iolink->flags & CRAT_IOLINK_FLAGS_BI_DIRECTIONAL)) {
> -		to_dev = kfd_topology_device_by_proximity_domain(id_to);
> +		to_dev = kfd_topology_device_by_proximity_domain_no_lock(id_to);
>   		if (!to_dev)
>   			return -ENODEV;
>   		/* same everything but the other direction */
> @@ -2225,7 +2225,7 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
>   	 */
>   	if (kdev->hive_id) {
>   		for (nid = 0; nid < proximity_domain; ++nid) {
> -			peer_dev = kfd_topology_device_by_proximity_domain(nid);
> +			peer_dev = kfd_topology_device_by_proximity_domain_no_lock(nid);
>   			if (!peer_dev->gpu)
>   				continue;
>   			if (peer_dev->gpu->hive_id != kdev->hive_id)
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> index e1b7e6afa920..8a43def1f638 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> @@ -1016,6 +1016,8 @@ int kfd_topology_add_device(struct kfd_dev *gpu);
>   int kfd_topology_remove_device(struct kfd_dev *gpu);
>   struct kfd_topology_device *kfd_topology_device_by_proximity_domain(
>   						uint32_t proximity_domain);
> +struct kfd_topology_device *kfd_topology_device_by_proximity_domain_no_lock(
> +						uint32_t proximity_domain);
>   struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id);
>   struct kfd_dev *kfd_device_by_id(uint32_t gpu_id);
>   struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev);
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
> index 3bdcae239bc0..874a273b81f7 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
> @@ -46,27 +46,38 @@ static struct list_head topology_device_list;
>   static struct kfd_system_properties sys_props;
>   
>   static DECLARE_RWSEM(topology_lock);
> -static atomic_t topology_crat_proximity_domain;
> +static uint32_t topology_crat_proximity_domain;
>   
> -struct kfd_topology_device *kfd_topology_device_by_proximity_domain(
> +struct kfd_topology_device *kfd_topology_device_by_proximity_domain_no_lock(
>   						uint32_t proximity_domain)
>   {
>   	struct kfd_topology_device *top_dev;
>   	struct kfd_topology_device *device = NULL;
>   
> -	down_read(&topology_lock);
> -
>   	list_for_each_entry(top_dev, &topology_device_list, list)
>   		if (top_dev->proximity_domain == proximity_domain) {
>   			device = top_dev;
>   			break;
>   		}
>   
> +	return device;
> +}
> +
> +struct kfd_topology_device *kfd_topology_device_by_proximity_domain(
> +						uint32_t proximity_domain)
> +{
> +	struct kfd_topology_device *device = NULL;
> +
> +	down_read(&topology_lock);
> +
> +	device = kfd_topology_device_by_proximity_domain_no_lock(
> +							proximity_domain);
>   	up_read(&topology_lock);
>   
>   	return device;
>   }
>   
> +
>   struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id)
>   {
>   	struct kfd_topology_device *top_dev = NULL;
> @@ -1060,7 +1071,7 @@ int kfd_topology_init(void)
>   	down_write(&topology_lock);
>   	kfd_topology_update_device_list(&temp_topology_device_list,
>   					&topology_device_list);
> -	atomic_set(&topology_crat_proximity_domain, sys_props.num_devices-1);
> +	topology_crat_proximity_domain = sys_props.num_devices-1;
>   	ret = kfd_topology_update_sysfs();
>   	up_write(&topology_lock);
>   
> @@ -1295,8 +1306,6 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
>   
>   	pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id);
>   
> -	proximity_domain = atomic_inc_return(&topology_crat_proximity_domain);
> -
>   	/* Include the CPU in xGMI hive if xGMI connected by assigning it the hive ID. */
>   	if (gpu->hive_id && gpu->adev->gmc.xgmi.connected_to_cpu) {
>   		struct kfd_topology_device *top_dev;
> @@ -1321,12 +1330,16 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
>   	 */
>   	dev = kfd_assign_gpu(gpu);
>   	if (!dev) {
> +		down_write(&topology_lock);
> +		proximity_domain = ++topology_crat_proximity_domain;
> +
>   		res = kfd_create_crat_image_virtual(&crat_image, &image_size,
>   						    COMPUTE_UNIT_GPU, gpu,
>   						    proximity_domain);
>   		if (res) {
>   			pr_err("Error creating VCRAT for GPU (ID: 0x%x)\n",
>   			       gpu_id);
> +			topology_crat_proximity_domain--;
>   			return res;
>   		}
>   		res = kfd_parse_crat_table(crat_image,
> @@ -1335,10 +1348,10 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
>   		if (res) {
>   			pr_err("Error parsing VCRAT for GPU (ID: 0x%x)\n",
>   			       gpu_id);
> +			topology_crat_proximity_domain--;
>   			goto err;
>   		}
>   
> -		down_write(&topology_lock);
>   		kfd_topology_update_device_list(&temp_topology_device_list,
>   			&topology_device_list);
>   
> @@ -1485,25 +1498,73 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
>   	return res;
>   }
>   
> +static void kfd_topology_update_io_links(int proximity_domain)
> +{
> +	struct kfd_topology_device *dev;
> +	struct kfd_iolink_properties *iolink, *p2plink, *tmp;
> +	/*
> +	 * The topology list currently is arranged in increasing
> +	 * order of proximity domain.
> +	 *
> +	 * Two things need to be done when a device is removed:
> +	 * 1. All the IO links to this device need to be
> +	 *    removed.
> +	 * 2. All nodes after the current device node need to move
> +	 *    up once this device node is removed from the topology
> +	 *    list. As a result, the proximity domain values for
> +	 *    all nodes after the node being deleted reduce by 1.
> +	 *    This would also cause the proximity domain values for
> +	 *    io links to be updated based on new proximity
> +	 *    domain values.
> +	 */
> +	list_for_each_entry(dev, &topology_device_list, list) {
> +		if (dev->proximity_domain > proximity_domain)
> +			dev->proximity_domain--;
> +
> +		list_for_each_entry_safe(iolink, tmp, &dev->io_link_props, list) {
> +			/*
> +			 * If there is an io link to the dev being deleted
> +			 * then remove that IO link also.
> +			 */
> +			if (iolink->node_to == proximity_domain) {
> +				list_del(&iolink->list);
> +				dev->io_link_count--;
> +				dev->node_props.io_links_count--;
> +			} else if (iolink->node_from > proximity_domain) {
> +				iolink->node_from--;
> +			} else if (iolink->node_to > proximity_domain) {
> +				iolink->node_to--;
> +			}
> +		}
> +
> +	}
> +}
> +
>   int kfd_topology_remove_device(struct kfd_dev *gpu)
>   {
>   	struct kfd_topology_device *dev, *tmp;
>   	uint32_t gpu_id;
>   	int res = -ENODEV;
> +	int i = 0;
>   
>   	down_write(&topology_lock);
>   
> -	list_for_each_entry_safe(dev, tmp, &topology_device_list, list)
> +	list_for_each_entry_safe(dev, tmp, &topology_device_list, list) {
>   		if (dev->gpu == gpu) {
>   			gpu_id = dev->gpu_id;
>   			kfd_remove_sysfs_node_entry(dev);
>   			kfd_release_topology_device(dev);
>   			sys_props.num_devices--;
> +			kfd_topology_update_io_links(i);
> +			topology_crat_proximity_domain = sys_props.num_devices-1;
> +			sys_props.generation_count++;
>   			res = 0;
>   			if (kfd_topology_update_sysfs() < 0)
>   				kfd_topology_release_sysfs();
>   			break;
>   		}
> +		i++;
> +	}
>   
>   	up_write(&topology_lock);
>   

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] drm/amdkfd: Cleanup IO links during KFD device removal
  2022-04-07 16:15 [PATCH] drm/amdkfd: Cleanup IO links during KFD device removal Mukul Joshi
  2022-04-07 17:05 ` Andrey Grodzovsky
@ 2022-04-12  0:16 ` Felix Kuehling
  2022-04-12  1:14   ` Joshi, Mukul
  1 sibling, 1 reply; 5+ messages in thread
From: Felix Kuehling @ 2022-04-12  0:16 UTC (permalink / raw)
  To: Mukul Joshi, amd-gfx; +Cc: Shuotao Xu

Am 2022-04-07 um 12:15 schrieb Mukul Joshi:
> Currently, the IO-links to the device being removed from topology,
> are not cleared. As a result, there would be dangling links left in
> the KFD topology. This patch aims to fix the following:
> 1. Cleanup all IO links to the device being removed.
> 2. Ensure that node numbering in sysfs and nodes proximity domain
>     values are consistent after the device is removed:
>     a. Adding a device and removing a GPU device are made mutually
>        exclusive.
>     b. The global proximity domain counter is no longer required to be
>        an atomic counter. A normal 32-bit counter can be used instead.
> 3. Update generation_count to let user-mode know that topology has
>     changed due to device removal.
>
> CC: Shuotao Xu <shuotaoxu@microsoft.com>
> Signed-off-by: Mukul Joshi <mukul.joshi@amd.com>

Looks good to me. I have two nit-picks inline.


> ---
>   drivers/gpu/drm/amd/amdkfd/kfd_crat.c     |  4 +-
>   drivers/gpu/drm/amd/amdkfd/kfd_priv.h     |  2 +
>   drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 79 ++++++++++++++++++++---
>   3 files changed, 74 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
> index 1eaabd2cb41b..afc8a7fcdad8 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
> @@ -1056,7 +1056,7 @@ static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink,
>   	 * table, add corresponded reversed direction link now.
>   	 */
>   	if (props && (iolink->flags & CRAT_IOLINK_FLAGS_BI_DIRECTIONAL)) {
> -		to_dev = kfd_topology_device_by_proximity_domain(id_to);
> +		to_dev = kfd_topology_device_by_proximity_domain_no_lock(id_to);
>   		if (!to_dev)
>   			return -ENODEV;
>   		/* same everything but the other direction */
> @@ -2225,7 +2225,7 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
>   	 */
>   	if (kdev->hive_id) {
>   		for (nid = 0; nid < proximity_domain; ++nid) {
> -			peer_dev = kfd_topology_device_by_proximity_domain(nid);
> +			peer_dev = kfd_topology_device_by_proximity_domain_no_lock(nid);
>   			if (!peer_dev->gpu)
>   				continue;
>   			if (peer_dev->gpu->hive_id != kdev->hive_id)
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> index e1b7e6afa920..8a43def1f638 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> @@ -1016,6 +1016,8 @@ int kfd_topology_add_device(struct kfd_dev *gpu);
>   int kfd_topology_remove_device(struct kfd_dev *gpu);
>   struct kfd_topology_device *kfd_topology_device_by_proximity_domain(
>   						uint32_t proximity_domain);
> +struct kfd_topology_device *kfd_topology_device_by_proximity_domain_no_lock(
> +						uint32_t proximity_domain);
>   struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id);
>   struct kfd_dev *kfd_device_by_id(uint32_t gpu_id);
>   struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev);
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
> index 3bdcae239bc0..874a273b81f7 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
> @@ -46,27 +46,38 @@ static struct list_head topology_device_list;
>   static struct kfd_system_properties sys_props;
>   
>   static DECLARE_RWSEM(topology_lock);
> -static atomic_t topology_crat_proximity_domain;
> +static uint32_t topology_crat_proximity_domain;
>   
> -struct kfd_topology_device *kfd_topology_device_by_proximity_domain(
> +struct kfd_topology_device *kfd_topology_device_by_proximity_domain_no_lock(
>   						uint32_t proximity_domain)

I remember we discussed this and I suggested splitting a no_lock version 
out of this function. But now I don't see it being used anywhere. Was 
that lost somewhere in refactoring or porting to the upstream branch? 
Maybe the no_lock version isn't needed any more.


>   {
>   	struct kfd_topology_device *top_dev;
>   	struct kfd_topology_device *device = NULL;
>   
> -	down_read(&topology_lock);
> -
>   	list_for_each_entry(top_dev, &topology_device_list, list)
>   		if (top_dev->proximity_domain == proximity_domain) {
>   			device = top_dev;
>   			break;
>   		}
>   
> +	return device;
> +}
> +
> +struct kfd_topology_device *kfd_topology_device_by_proximity_domain(
> +						uint32_t proximity_domain)
> +{
> +	struct kfd_topology_device *device = NULL;
> +
> +	down_read(&topology_lock);
> +
> +	device = kfd_topology_device_by_proximity_domain_no_lock(
> +							proximity_domain);
>   	up_read(&topology_lock);
>   
>   	return device;
>   }
>   
> +
>   struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id)
>   {
>   	struct kfd_topology_device *top_dev = NULL;
> @@ -1060,7 +1071,7 @@ int kfd_topology_init(void)
>   	down_write(&topology_lock);
>   	kfd_topology_update_device_list(&temp_topology_device_list,
>   					&topology_device_list);
> -	atomic_set(&topology_crat_proximity_domain, sys_props.num_devices-1);
> +	topology_crat_proximity_domain = sys_props.num_devices-1;
>   	ret = kfd_topology_update_sysfs();
>   	up_write(&topology_lock);
>   
> @@ -1295,8 +1306,6 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
>   
>   	pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id);
>   
> -	proximity_domain = atomic_inc_return(&topology_crat_proximity_domain);
> -
>   	/* Include the CPU in xGMI hive if xGMI connected by assigning it the hive ID. */
>   	if (gpu->hive_id && gpu->adev->gmc.xgmi.connected_to_cpu) {
>   		struct kfd_topology_device *top_dev;
> @@ -1321,12 +1330,16 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
>   	 */
>   	dev = kfd_assign_gpu(gpu);
>   	if (!dev) {
> +		down_write(&topology_lock);
> +		proximity_domain = ++topology_crat_proximity_domain;
> +
>   		res = kfd_create_crat_image_virtual(&crat_image, &image_size,
>   						    COMPUTE_UNIT_GPU, gpu,
>   						    proximity_domain);
>   		if (res) {
>   			pr_err("Error creating VCRAT for GPU (ID: 0x%x)\n",
>   			       gpu_id);
> +			topology_crat_proximity_domain--;
>   			return res;
>   		}
>   		res = kfd_parse_crat_table(crat_image,
> @@ -1335,10 +1348,10 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
>   		if (res) {
>   			pr_err("Error parsing VCRAT for GPU (ID: 0x%x)\n",
>   			       gpu_id);
> +			topology_crat_proximity_domain--;
>   			goto err;
>   		}
>   
> -		down_write(&topology_lock);
>   		kfd_topology_update_device_list(&temp_topology_device_list,
>   			&topology_device_list);
>   
> @@ -1485,25 +1498,73 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
>   	return res;
>   }
>   
> +static void kfd_topology_update_io_links(int proximity_domain)
> +{
> +	struct kfd_topology_device *dev;
> +	struct kfd_iolink_properties *iolink, *p2plink, *tmp;
> +	/*
> +	 * The topology list currently is arranged in increasing
> +	 * order of proximity domain.
> +	 *
> +	 * Two things need to be done when a device is removed:
> +	 * 1. All the IO links to this device need to be
> +	 *    removed.
> +	 * 2. All nodes after the current device node need to move
> +	 *    up once this device node is removed from the topology
> +	 *    list. As a result, the proximity domain values for
> +	 *    all nodes after the node being deleted reduce by 1.
> +	 *    This would also cause the proximity domain values for
> +	 *    io links to be updated based on new proximity
> +	 *    domain values.
> +	 */

I'd put this comment in front of the function, not in the middle of it. 
You can make it a proper kernel-doc comment, especially since the 
function name is a bit generic (and I can't think of a better one that 
isn't excessively long).

Regards,
   Felix


> +	list_for_each_entry(dev, &topology_device_list, list) {
> +		if (dev->proximity_domain > proximity_domain)
> +			dev->proximity_domain--;
> +
> +		list_for_each_entry_safe(iolink, tmp, &dev->io_link_props, list) {
> +			/*
> +			 * If there is an io link to the dev being deleted
> +			 * then remove that IO link also.
> +			 */
> +			if (iolink->node_to == proximity_domain) {
> +				list_del(&iolink->list);
> +				dev->io_link_count--;
> +				dev->node_props.io_links_count--;
> +			} else if (iolink->node_from > proximity_domain) {
> +				iolink->node_from--;
> +			} else if (iolink->node_to > proximity_domain) {
> +				iolink->node_to--;
> +			}
> +		}
> +
> +	}
> +}
> +
>   int kfd_topology_remove_device(struct kfd_dev *gpu)
>   {
>   	struct kfd_topology_device *dev, *tmp;
>   	uint32_t gpu_id;
>   	int res = -ENODEV;
> +	int i = 0;
>   
>   	down_write(&topology_lock);
>   
> -	list_for_each_entry_safe(dev, tmp, &topology_device_list, list)
> +	list_for_each_entry_safe(dev, tmp, &topology_device_list, list) {
>   		if (dev->gpu == gpu) {
>   			gpu_id = dev->gpu_id;
>   			kfd_remove_sysfs_node_entry(dev);
>   			kfd_release_topology_device(dev);
>   			sys_props.num_devices--;
> +			kfd_topology_update_io_links(i);
> +			topology_crat_proximity_domain = sys_props.num_devices-1;
> +			sys_props.generation_count++;
>   			res = 0;
>   			if (kfd_topology_update_sysfs() < 0)
>   				kfd_topology_release_sysfs();
>   			break;
>   		}
> +		i++;
> +	}
>   
>   	up_write(&topology_lock);
>   

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH] drm/amdkfd: Cleanup IO links during KFD device removal
  2022-04-12  0:16 ` Felix Kuehling
@ 2022-04-12  1:14   ` Joshi, Mukul
  2022-04-12  1:21     ` Felix Kuehling
  0 siblings, 1 reply; 5+ messages in thread
From: Joshi, Mukul @ 2022-04-12  1:14 UTC (permalink / raw)
  To: Kuehling, Felix, amd-gfx; +Cc: Shuotao Xu

[AMD Official Use Only]



> -----Original Message-----
> From: Kuehling, Felix <Felix.Kuehling@amd.com>
> Sent: Monday, April 11, 2022 8:16 PM
> To: Joshi, Mukul <Mukul.Joshi@amd.com>; amd-gfx@lists.freedesktop.org
> Cc: Shuotao Xu <shuotaoxu@microsoft.com>
> Subject: Re: [PATCH] drm/amdkfd: Cleanup IO links during KFD device
> removal
> 
> Am 2022-04-07 um 12:15 schrieb Mukul Joshi:
> > Currently, the IO-links to the device being removed from topology, are
> > not cleared. As a result, there would be dangling links left in the
> > KFD topology. This patch aims to fix the following:
> > 1. Cleanup all IO links to the device being removed.
> > 2. Ensure that node numbering in sysfs and nodes proximity domain
> >     values are consistent after the device is removed:
> >     a. Adding a device and removing a GPU device are made mutually
> >        exclusive.
> >     b. The global proximity domain counter is no longer required to be
> >        an atomic counter. A normal 32-bit counter can be used instead.
> > 3. Update generation_count to let user-mode know that topology has
> >     changed due to device removal.
> >
> > CC: Shuotao Xu <shuotaoxu@microsoft.com>
> > Signed-off-by: Mukul Joshi <mukul.joshi@amd.com>
> 
> Looks good to me. I have two nit-picks inline.
> 
> 
> > ---
> >   drivers/gpu/drm/amd/amdkfd/kfd_crat.c     |  4 +-
> >   drivers/gpu/drm/amd/amdkfd/kfd_priv.h     |  2 +
> >   drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 79
> ++++++++++++++++++++---
> >   3 files changed, 74 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
> > b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
> > index 1eaabd2cb41b..afc8a7fcdad8 100644
> > --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
> > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
> > @@ -1056,7 +1056,7 @@ static int kfd_parse_subtype_iolink(struct
> crat_subtype_iolink *iolink,
> >   	 * table, add corresponded reversed direction link now.
> >   	 */
> >   	if (props && (iolink->flags & CRAT_IOLINK_FLAGS_BI_DIRECTIONAL))
> {
> > -		to_dev =
> kfd_topology_device_by_proximity_domain(id_to);
> > +		to_dev =
> kfd_topology_device_by_proximity_domain_no_lock(id_to);
> >   		if (!to_dev)
> >   			return -ENODEV;
> >   		/* same everything but the other direction */ @@ -2225,7
> +2225,7
> > @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
> >   	 */
> >   	if (kdev->hive_id) {
> >   		for (nid = 0; nid < proximity_domain; ++nid) {
> > -			peer_dev =
> kfd_topology_device_by_proximity_domain(nid);
> > +			peer_dev =
> kfd_topology_device_by_proximity_domain_no_lock(nid);
> >   			if (!peer_dev->gpu)
> >   				continue;
> >   			if (peer_dev->gpu->hive_id != kdev->hive_id) diff --
> git
> > a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> > b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> > index e1b7e6afa920..8a43def1f638 100644
> > --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> > @@ -1016,6 +1016,8 @@ int kfd_topology_add_device(struct kfd_dev
> *gpu);
> >   int kfd_topology_remove_device(struct kfd_dev *gpu);
> >   struct kfd_topology_device
> *kfd_topology_device_by_proximity_domain(
> >   						uint32_t proximity_domain);
> > +struct kfd_topology_device
> *kfd_topology_device_by_proximity_domain_no_lock(
> > +						uint32_t proximity_domain);
> >   struct kfd_topology_device *kfd_topology_device_by_id(uint32_t
> gpu_id);
> >   struct kfd_dev *kfd_device_by_id(uint32_t gpu_id);
> >   struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev);
> > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
> > b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
> > index 3bdcae239bc0..874a273b81f7 100644
> > --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
> > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
> > @@ -46,27 +46,38 @@ static struct list_head topology_device_list;
> >   static struct kfd_system_properties sys_props;
> >
> >   static DECLARE_RWSEM(topology_lock); -static atomic_t
> > topology_crat_proximity_domain;
> > +static uint32_t topology_crat_proximity_domain;
> >
> > -struct kfd_topology_device
> *kfd_topology_device_by_proximity_domain(
> > +struct kfd_topology_device
> > +*kfd_topology_device_by_proximity_domain_no_lock(
> >   						uint32_t proximity_domain)
> 
> I remember we discussed this and I suggested splitting a no_lock version out
> of this function. But now I don't see it being used anywhere. Was that lost
> somewhere in refactoring or porting to the upstream branch?
> Maybe the no_lock version isn't needed any more.
> 
Its used in the changes in kfd_crat.c (in kfd_create_vcrat_image_gpu() and
kfd_parse_subtype_iolink ()) and  below in kfd_topology_device_by_proximity_domain().

> 
> >   {
> >   	struct kfd_topology_device *top_dev;
> >   	struct kfd_topology_device *device = NULL;
> >
> > -	down_read(&topology_lock);
> > -
> >   	list_for_each_entry(top_dev, &topology_device_list, list)
> >   		if (top_dev->proximity_domain == proximity_domain) {
> >   			device = top_dev;
> >   			break;
> >   		}
> >
> > +	return device;
> > +}
> > +
> > +struct kfd_topology_device
> *kfd_topology_device_by_proximity_domain(
> > +						uint32_t proximity_domain)
> > +{
> > +	struct kfd_topology_device *device = NULL;
> > +
> > +	down_read(&topology_lock);
> > +
> > +	device = kfd_topology_device_by_proximity_domain_no_lock(
> > +							proximity_domain);
> >   	up_read(&topology_lock);
> >
> >   	return device;
> >   }
> >
> > +
> >   struct kfd_topology_device *kfd_topology_device_by_id(uint32_t
> gpu_id)
> >   {
> >   	struct kfd_topology_device *top_dev = NULL; @@ -1060,7 +1071,7
> @@
> > int kfd_topology_init(void)
> >   	down_write(&topology_lock);
> >   	kfd_topology_update_device_list(&temp_topology_device_list,
> >   					&topology_device_list);
> > -	atomic_set(&topology_crat_proximity_domain,
> sys_props.num_devices-1);
> > +	topology_crat_proximity_domain = sys_props.num_devices-1;
> >   	ret = kfd_topology_update_sysfs();
> >   	up_write(&topology_lock);
> >
> > @@ -1295,8 +1306,6 @@ int kfd_topology_add_device(struct kfd_dev
> *gpu)
> >
> >   	pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id);
> >
> > -	proximity_domain =
> atomic_inc_return(&topology_crat_proximity_domain);
> > -
> >   	/* Include the CPU in xGMI hive if xGMI connected by assigning it the
> hive ID. */
> >   	if (gpu->hive_id && gpu->adev->gmc.xgmi.connected_to_cpu) {
> >   		struct kfd_topology_device *top_dev; @@ -1321,12
> +1330,16 @@ int
> > kfd_topology_add_device(struct kfd_dev *gpu)
> >   	 */
> >   	dev = kfd_assign_gpu(gpu);
> >   	if (!dev) {
> > +		down_write(&topology_lock);
> > +		proximity_domain = ++topology_crat_proximity_domain;
> > +
> >   		res = kfd_create_crat_image_virtual(&crat_image,
> &image_size,
> >   						    COMPUTE_UNIT_GPU,
> gpu,
> >   						    proximity_domain);
> >   		if (res) {
> >   			pr_err("Error creating VCRAT for GPU (ID: 0x%x)\n",
> >   			       gpu_id);
> > +			topology_crat_proximity_domain--;
> >   			return res;
> >   		}
> >   		res = kfd_parse_crat_table(crat_image, @@ -1335,10
> +1348,10 @@ int
> > kfd_topology_add_device(struct kfd_dev *gpu)
> >   		if (res) {
> >   			pr_err("Error parsing VCRAT for GPU (ID: 0x%x)\n",
> >   			       gpu_id);
> > +			topology_crat_proximity_domain--;
> >   			goto err;
> >   		}
> >
> > -		down_write(&topology_lock);
> >
> 	kfd_topology_update_device_list(&temp_topology_device_list,
> >   			&topology_device_list);
> >
> > @@ -1485,25 +1498,73 @@ int kfd_topology_add_device(struct kfd_dev
> *gpu)
> >   	return res;
> >   }
> >
> > +static void kfd_topology_update_io_links(int proximity_domain) {
> > +	struct kfd_topology_device *dev;
> > +	struct kfd_iolink_properties *iolink, *p2plink, *tmp;
> > +	/*
> > +	 * The topology list currently is arranged in increasing
> > +	 * order of proximity domain.
> > +	 *
> > +	 * Two things need to be done when a device is removed:
> > +	 * 1. All the IO links to this device need to be
> > +	 *    removed.
> > +	 * 2. All nodes after the current device node need to move
> > +	 *    up once this device node is removed from the topology
> > +	 *    list. As a result, the proximity domain values for
> > +	 *    all nodes after the node being deleted reduce by 1.
> > +	 *    This would also cause the proximity domain values for
> > +	 *    io links to be updated based on new proximity
> > +	 *    domain values.
> > +	 */
> 
> I'd put this comment in front of the function, not in the middle of it.
> You can make it a proper kernel-doc comment, especially since the function
> name is a bit generic (and I can't think of a better one that isn't excessively
> long).
> 
Sure will do that and send a v2.

Regards,
Mukul

> Regards,
>    Felix
> 
> 
> > +	list_for_each_entry(dev, &topology_device_list, list) {
> > +		if (dev->proximity_domain > proximity_domain)
> > +			dev->proximity_domain--;
> > +
> > +		list_for_each_entry_safe(iolink, tmp, &dev->io_link_props,
> list) {
> > +			/*
> > +			 * If there is an io link to the dev being deleted
> > +			 * then remove that IO link also.
> > +			 */
> > +			if (iolink->node_to == proximity_domain) {
> > +				list_del(&iolink->list);
> > +				dev->io_link_count--;
> > +				dev->node_props.io_links_count--;
> > +			} else if (iolink->node_from > proximity_domain) {
> > +				iolink->node_from--;
> > +			} else if (iolink->node_to > proximity_domain) {
> > +				iolink->node_to--;
> > +			}
> > +		}
> > +
> > +	}
> > +}
> > +
> >   int kfd_topology_remove_device(struct kfd_dev *gpu)
> >   {
> >   	struct kfd_topology_device *dev, *tmp;
> >   	uint32_t gpu_id;
> >   	int res = -ENODEV;
> > +	int i = 0;
> >
> >   	down_write(&topology_lock);
> >
> > -	list_for_each_entry_safe(dev, tmp, &topology_device_list, list)
> > +	list_for_each_entry_safe(dev, tmp, &topology_device_list, list) {
> >   		if (dev->gpu == gpu) {
> >   			gpu_id = dev->gpu_id;
> >   			kfd_remove_sysfs_node_entry(dev);
> >   			kfd_release_topology_device(dev);
> >   			sys_props.num_devices--;
> > +			kfd_topology_update_io_links(i);
> > +			topology_crat_proximity_domain =
> sys_props.num_devices-1;
> > +			sys_props.generation_count++;
> >   			res = 0;
> >   			if (kfd_topology_update_sysfs() < 0)
> >   				kfd_topology_release_sysfs();
> >   			break;
> >   		}
> > +		i++;
> > +	}
> >
> >   	up_write(&topology_lock);
> >

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] drm/amdkfd: Cleanup IO links during KFD device removal
  2022-04-12  1:14   ` Joshi, Mukul
@ 2022-04-12  1:21     ` Felix Kuehling
  0 siblings, 0 replies; 5+ messages in thread
From: Felix Kuehling @ 2022-04-12  1:21 UTC (permalink / raw)
  To: Joshi, Mukul, amd-gfx; +Cc: Shuotao Xu

Am 2022-04-11 um 21:14 schrieb Joshi, Mukul:
> [AMD Official Use Only]
>
>
>
>> -----Original Message-----
>> From: Kuehling, Felix <Felix.Kuehling@amd.com>
>> Sent: Monday, April 11, 2022 8:16 PM
>> To: Joshi, Mukul <Mukul.Joshi@amd.com>; amd-gfx@lists.freedesktop.org
>> Cc: Shuotao Xu <shuotaoxu@microsoft.com>
>> Subject: Re: [PATCH] drm/amdkfd: Cleanup IO links during KFD device
>> removal
>>
>> Am 2022-04-07 um 12:15 schrieb Mukul Joshi:
>>> Currently, the IO-links to the device being removed from topology, are
>>> not cleared. As a result, there would be dangling links left in the
>>> KFD topology. This patch aims to fix the following:
>>> 1. Cleanup all IO links to the device being removed.
>>> 2. Ensure that node numbering in sysfs and nodes proximity domain
>>>      values are consistent after the device is removed:
>>>      a. Adding a device and removing a GPU device are made mutually
>>>         exclusive.
>>>      b. The global proximity domain counter is no longer required to be
>>>         an atomic counter. A normal 32-bit counter can be used instead.
>>> 3. Update generation_count to let user-mode know that topology has
>>>      changed due to device removal.
>>>
>>> CC: Shuotao Xu <shuotaoxu@microsoft.com>
>>> Signed-off-by: Mukul Joshi <mukul.joshi@amd.com>
>> Looks good to me. I have two nit-picks inline.
>>
>>
>>> ---
>>>    drivers/gpu/drm/amd/amdkfd/kfd_crat.c     |  4 +-
>>>    drivers/gpu/drm/amd/amdkfd/kfd_priv.h     |  2 +
>>>    drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 79
>> ++++++++++++++++++++---
>>>    3 files changed, 74 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
>>> b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
>>> index 1eaabd2cb41b..afc8a7fcdad8 100644
>>> --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
>>> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
>>> @@ -1056,7 +1056,7 @@ static int kfd_parse_subtype_iolink(struct
>> crat_subtype_iolink *iolink,
>>>    	 * table, add corresponded reversed direction link now.
>>>    	 */
>>>    	if (props && (iolink->flags & CRAT_IOLINK_FLAGS_BI_DIRECTIONAL))
>> {
>>> -		to_dev =
>> kfd_topology_device_by_proximity_domain(id_to);
>>> +		to_dev =
>> kfd_topology_device_by_proximity_domain_no_lock(id_to);
>>>    		if (!to_dev)
>>>    			return -ENODEV;
>>>    		/* same everything but the other direction */ @@ -2225,7
>> +2225,7
>>> @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
>>>    	 */
>>>    	if (kdev->hive_id) {
>>>    		for (nid = 0; nid < proximity_domain; ++nid) {
>>> -			peer_dev =
>> kfd_topology_device_by_proximity_domain(nid);
>>> +			peer_dev =
>> kfd_topology_device_by_proximity_domain_no_lock(nid);
>>>    			if (!peer_dev->gpu)
>>>    				continue;
>>>    			if (peer_dev->gpu->hive_id != kdev->hive_id) diff --
>> git
>>> a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
>>> b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
>>> index e1b7e6afa920..8a43def1f638 100644
>>> --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
>>> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
>>> @@ -1016,6 +1016,8 @@ int kfd_topology_add_device(struct kfd_dev
>> *gpu);
>>>    int kfd_topology_remove_device(struct kfd_dev *gpu);
>>>    struct kfd_topology_device
>> *kfd_topology_device_by_proximity_domain(
>>>    						uint32_t proximity_domain);
>>> +struct kfd_topology_device
>> *kfd_topology_device_by_proximity_domain_no_lock(
>>> +						uint32_t proximity_domain);
>>>    struct kfd_topology_device *kfd_topology_device_by_id(uint32_t
>> gpu_id);
>>>    struct kfd_dev *kfd_device_by_id(uint32_t gpu_id);
>>>    struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev);
>>> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
>>> b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
>>> index 3bdcae239bc0..874a273b81f7 100644
>>> --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
>>> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
>>> @@ -46,27 +46,38 @@ static struct list_head topology_device_list;
>>>    static struct kfd_system_properties sys_props;
>>>
>>>    static DECLARE_RWSEM(topology_lock); -static atomic_t
>>> topology_crat_proximity_domain;
>>> +static uint32_t topology_crat_proximity_domain;
>>>
>>> -struct kfd_topology_device
>> *kfd_topology_device_by_proximity_domain(
>>> +struct kfd_topology_device
>>> +*kfd_topology_device_by_proximity_domain_no_lock(
>>>    						uint32_t proximity_domain)
>> I remember we discussed this and I suggested splitting a no_lock version out
>> of this function. But now I don't see it being used anywhere. Was that lost
>> somewhere in refactoring or porting to the upstream branch?
>> Maybe the no_lock version isn't needed any more.
>>
> Its used in the changes in kfd_crat.c (in kfd_create_vcrat_image_gpu() and
> kfd_parse_subtype_iolink ()) and  below in kfd_topology_device_by_proximity_domain().

You're right, I missed the changes in kfd_crat.c. And they are needed 
because the whole CRAT table parsing is now under the topology lock. 
Thanks for the reminder.

Regards,
   Felix


>
>>>    {
>>>    	struct kfd_topology_device *top_dev;
>>>    	struct kfd_topology_device *device = NULL;
>>>
>>> -	down_read(&topology_lock);
>>> -
>>>    	list_for_each_entry(top_dev, &topology_device_list, list)
>>>    		if (top_dev->proximity_domain == proximity_domain) {
>>>    			device = top_dev;
>>>    			break;
>>>    		}
>>>
>>> +	return device;
>>> +}
>>> +
>>> +struct kfd_topology_device
>> *kfd_topology_device_by_proximity_domain(
>>> +						uint32_t proximity_domain)
>>> +{
>>> +	struct kfd_topology_device *device = NULL;
>>> +
>>> +	down_read(&topology_lock);
>>> +
>>> +	device = kfd_topology_device_by_proximity_domain_no_lock(
>>> +							proximity_domain);
>>>    	up_read(&topology_lock);
>>>
>>>    	return device;
>>>    }
>>>
>>> +
>>>    struct kfd_topology_device *kfd_topology_device_by_id(uint32_t
>> gpu_id)
>>>    {
>>>    	struct kfd_topology_device *top_dev = NULL; @@ -1060,7 +1071,7
>> @@
>>> int kfd_topology_init(void)
>>>    	down_write(&topology_lock);
>>>    	kfd_topology_update_device_list(&temp_topology_device_list,
>>>    					&topology_device_list);
>>> -	atomic_set(&topology_crat_proximity_domain,
>> sys_props.num_devices-1);
>>> +	topology_crat_proximity_domain = sys_props.num_devices-1;
>>>    	ret = kfd_topology_update_sysfs();
>>>    	up_write(&topology_lock);
>>>
>>> @@ -1295,8 +1306,6 @@ int kfd_topology_add_device(struct kfd_dev
>> *gpu)
>>>    	pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id);
>>>
>>> -	proximity_domain =
>> atomic_inc_return(&topology_crat_proximity_domain);
>>> -
>>>    	/* Include the CPU in xGMI hive if xGMI connected by assigning it the
>> hive ID. */
>>>    	if (gpu->hive_id && gpu->adev->gmc.xgmi.connected_to_cpu) {
>>>    		struct kfd_topology_device *top_dev; @@ -1321,12
>> +1330,16 @@ int
>>> kfd_topology_add_device(struct kfd_dev *gpu)
>>>    	 */
>>>    	dev = kfd_assign_gpu(gpu);
>>>    	if (!dev) {
>>> +		down_write(&topology_lock);
>>> +		proximity_domain = ++topology_crat_proximity_domain;
>>> +
>>>    		res = kfd_create_crat_image_virtual(&crat_image,
>> &image_size,
>>>    						    COMPUTE_UNIT_GPU,
>> gpu,
>>>    						    proximity_domain);
>>>    		if (res) {
>>>    			pr_err("Error creating VCRAT for GPU (ID: 0x%x)\n",
>>>    			       gpu_id);
>>> +			topology_crat_proximity_domain--;
>>>    			return res;
>>>    		}
>>>    		res = kfd_parse_crat_table(crat_image, @@ -1335,10
>> +1348,10 @@ int
>>> kfd_topology_add_device(struct kfd_dev *gpu)
>>>    		if (res) {
>>>    			pr_err("Error parsing VCRAT for GPU (ID: 0x%x)\n",
>>>    			       gpu_id);
>>> +			topology_crat_proximity_domain--;
>>>    			goto err;
>>>    		}
>>>
>>> -		down_write(&topology_lock);
>>>
>> 	kfd_topology_update_device_list(&temp_topology_device_list,
>>>    			&topology_device_list);
>>>
>>> @@ -1485,25 +1498,73 @@ int kfd_topology_add_device(struct kfd_dev
>> *gpu)
>>>    	return res;
>>>    }
>>>
>>> +static void kfd_topology_update_io_links(int proximity_domain) {
>>> +	struct kfd_topology_device *dev;
>>> +	struct kfd_iolink_properties *iolink, *p2plink, *tmp;
>>> +	/*
>>> +	 * The topology list currently is arranged in increasing
>>> +	 * order of proximity domain.
>>> +	 *
>>> +	 * Two things need to be done when a device is removed:
>>> +	 * 1. All the IO links to this device need to be
>>> +	 *    removed.
>>> +	 * 2. All nodes after the current device node need to move
>>> +	 *    up once this device node is removed from the topology
>>> +	 *    list. As a result, the proximity domain values for
>>> +	 *    all nodes after the node being deleted reduce by 1.
>>> +	 *    This would also cause the proximity domain values for
>>> +	 *    io links to be updated based on new proximity
>>> +	 *    domain values.
>>> +	 */
>> I'd put this comment in front of the function, not in the middle of it.
>> You can make it a proper kernel-doc comment, especially since the function
>> name is a bit generic (and I can't think of a better one that isn't excessively
>> long).
>>
> Sure will do that and send a v2.
>
> Regards,
> Mukul
>
>> Regards,
>>     Felix
>>
>>
>>> +	list_for_each_entry(dev, &topology_device_list, list) {
>>> +		if (dev->proximity_domain > proximity_domain)
>>> +			dev->proximity_domain--;
>>> +
>>> +		list_for_each_entry_safe(iolink, tmp, &dev->io_link_props,
>> list) {
>>> +			/*
>>> +			 * If there is an io link to the dev being deleted
>>> +			 * then remove that IO link also.
>>> +			 */
>>> +			if (iolink->node_to == proximity_domain) {
>>> +				list_del(&iolink->list);
>>> +				dev->io_link_count--;
>>> +				dev->node_props.io_links_count--;
>>> +			} else if (iolink->node_from > proximity_domain) {
>>> +				iolink->node_from--;
>>> +			} else if (iolink->node_to > proximity_domain) {
>>> +				iolink->node_to--;
>>> +			}
>>> +		}
>>> +
>>> +	}
>>> +}
>>> +
>>>    int kfd_topology_remove_device(struct kfd_dev *gpu)
>>>    {
>>>    	struct kfd_topology_device *dev, *tmp;
>>>    	uint32_t gpu_id;
>>>    	int res = -ENODEV;
>>> +	int i = 0;
>>>
>>>    	down_write(&topology_lock);
>>>
>>> -	list_for_each_entry_safe(dev, tmp, &topology_device_list, list)
>>> +	list_for_each_entry_safe(dev, tmp, &topology_device_list, list) {
>>>    		if (dev->gpu == gpu) {
>>>    			gpu_id = dev->gpu_id;
>>>    			kfd_remove_sysfs_node_entry(dev);
>>>    			kfd_release_topology_device(dev);
>>>    			sys_props.num_devices--;
>>> +			kfd_topology_update_io_links(i);
>>> +			topology_crat_proximity_domain =
>> sys_props.num_devices-1;
>>> +			sys_props.generation_count++;
>>>    			res = 0;
>>>    			if (kfd_topology_update_sysfs() < 0)
>>>    				kfd_topology_release_sysfs();
>>>    			break;
>>>    		}
>>> +		i++;
>>> +	}
>>>
>>>    	up_write(&topology_lock);
>>>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-04-12  1:21 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-07 16:15 [PATCH] drm/amdkfd: Cleanup IO links during KFD device removal Mukul Joshi
2022-04-07 17:05 ` Andrey Grodzovsky
2022-04-12  0:16 ` Felix Kuehling
2022-04-12  1:14   ` Joshi, Mukul
2022-04-12  1:21     ` Felix Kuehling

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).