mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	drm/amdkfd: Ensure gpu_id is unique
gpu_id needs to be unique for user space to identify GPUs via KFD
interface. In the current implementation there is a very small
probability of having non unique gpu_ids.
v2: Add check to confirm if gpu_id is unique. If not unique, find one
    Changed commit header to reflect the above
v3: Use crc16 as suggested-by: Lijo Lazar <lijo.lazar@amd.com>
    Ensure that gpu_id != 0
Signed-off-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
			
			
This commit is contained in:
		
							parent
							
								
									b712d7c201
								
							
						
					
					
						commit
						3ed181b8ff
					
				
					 1 changed files with 34 additions and 6 deletions
				
			
		| 
						 | 
					@ -31,6 +31,7 @@
 | 
				
			||||||
#include <linux/log2.h>
 | 
					#include <linux/log2.h>
 | 
				
			||||||
#include <linux/dmi.h>
 | 
					#include <linux/dmi.h>
 | 
				
			||||||
#include <linux/atomic.h>
 | 
					#include <linux/atomic.h>
 | 
				
			||||||
 | 
					#include <linux/crc16.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "kfd_priv.h"
 | 
					#include "kfd_priv.h"
 | 
				
			||||||
#include "kfd_crat.h"
 | 
					#include "kfd_crat.h"
 | 
				
			||||||
| 
						 | 
					@ -1091,14 +1092,17 @@ void kfd_topology_shutdown(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint32_t kfd_generate_gpu_id(struct kfd_node *gpu)
 | 
					static uint32_t kfd_generate_gpu_id(struct kfd_node *gpu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint32_t hashout;
 | 
						uint32_t gpu_id;
 | 
				
			||||||
	uint32_t buf[8];
 | 
						uint32_t buf[8];
 | 
				
			||||||
	uint64_t local_mem_size;
 | 
						uint64_t local_mem_size;
 | 
				
			||||||
	int i;
 | 
						struct kfd_topology_device *dev;
 | 
				
			||||||
 | 
						bool is_unique;
 | 
				
			||||||
 | 
						uint8_t *crc_buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!gpu)
 | 
						if (!gpu)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						crc_buf = (uint8_t *)&buf;
 | 
				
			||||||
	local_mem_size = gpu->local_mem_info.local_mem_size_private +
 | 
						local_mem_size = gpu->local_mem_info.local_mem_size_private +
 | 
				
			||||||
			gpu->local_mem_info.local_mem_size_public;
 | 
								gpu->local_mem_info.local_mem_size_public;
 | 
				
			||||||
	buf[0] = gpu->adev->pdev->devfn;
 | 
						buf[0] = gpu->adev->pdev->devfn;
 | 
				
			||||||
| 
						 | 
					@ -1111,10 +1115,34 @@ static uint32_t kfd_generate_gpu_id(struct kfd_node *gpu)
 | 
				
			||||||
	buf[6] = upper_32_bits(local_mem_size);
 | 
						buf[6] = upper_32_bits(local_mem_size);
 | 
				
			||||||
	buf[7] = (ffs(gpu->xcc_mask) - 1) | (NUM_XCC(gpu->xcc_mask) << 16);
 | 
						buf[7] = (ffs(gpu->xcc_mask) - 1) | (NUM_XCC(gpu->xcc_mask) << 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0, hashout = 0; i < 8; i++)
 | 
						gpu_id = crc16(0, crc_buf, sizeof(buf)) &
 | 
				
			||||||
		hashout ^= hash_32(buf[i], KFD_GPU_ID_HASH_WIDTH);
 | 
							 ((1 << KFD_GPU_ID_HASH_WIDTH) - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return hashout;
 | 
						/* There is a very small possibility when generating a
 | 
				
			||||||
 | 
						 * 16 (KFD_GPU_ID_HASH_WIDTH) bit value from 8 word buffer
 | 
				
			||||||
 | 
						 * that the value could be 0 or non-unique. So, check if
 | 
				
			||||||
 | 
						 * it is unique and non-zero. If not unique increment till
 | 
				
			||||||
 | 
						 * unique one is found. In case of overflow, restart from 1
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						down_read(&topology_lock);
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							is_unique = true;
 | 
				
			||||||
 | 
							if (!gpu_id)
 | 
				
			||||||
 | 
								gpu_id = 1;
 | 
				
			||||||
 | 
							list_for_each_entry(dev, &topology_device_list, list) {
 | 
				
			||||||
 | 
								if (dev->gpu && dev->gpu_id == gpu_id) {
 | 
				
			||||||
 | 
									is_unique = false;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (unlikely(!is_unique))
 | 
				
			||||||
 | 
								gpu_id = (gpu_id + 1) &
 | 
				
			||||||
 | 
									  ((1 << KFD_GPU_ID_HASH_WIDTH) - 1);
 | 
				
			||||||
 | 
						} while (!is_unique);
 | 
				
			||||||
 | 
						up_read(&topology_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return gpu_id;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/* kfd_assign_gpu - Attach @gpu to the correct kfd topology device. If
 | 
					/* kfd_assign_gpu - Attach @gpu to the correct kfd topology device. If
 | 
				
			||||||
 *		the GPU device is not already present in the topology device
 | 
					 *		the GPU device is not already present in the topology device
 | 
				
			||||||
| 
						 | 
					@ -1945,7 +1973,6 @@ int kfd_topology_add_device(struct kfd_node *gpu)
 | 
				
			||||||
	struct amdgpu_gfx_config *gfx_info = &gpu->adev->gfx.config;
 | 
						struct amdgpu_gfx_config *gfx_info = &gpu->adev->gfx.config;
 | 
				
			||||||
	struct amdgpu_cu_info *cu_info = &gpu->adev->gfx.cu_info;
 | 
						struct amdgpu_cu_info *cu_info = &gpu->adev->gfx.cu_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gpu_id = kfd_generate_gpu_id(gpu);
 | 
					 | 
				
			||||||
	if (gpu->xcp && !gpu->xcp->ddev) {
 | 
						if (gpu->xcp && !gpu->xcp->ddev) {
 | 
				
			||||||
		dev_warn(gpu->adev->dev,
 | 
							dev_warn(gpu->adev->dev,
 | 
				
			||||||
			 "Won't add GPU to topology since it has no drm node assigned.");
 | 
								 "Won't add GPU to topology since it has no drm node assigned.");
 | 
				
			||||||
| 
						 | 
					@ -1968,6 +1995,7 @@ int kfd_topology_add_device(struct kfd_node *gpu)
 | 
				
			||||||
	if (res)
 | 
						if (res)
 | 
				
			||||||
		return res;
 | 
							return res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gpu_id = kfd_generate_gpu_id(gpu);
 | 
				
			||||||
	dev->gpu_id = gpu_id;
 | 
						dev->gpu_id = gpu_id;
 | 
				
			||||||
	gpu->id = gpu_id;
 | 
						gpu->id = gpu_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue