[PATCH] drm/amdgpu: Expose rfc4122 compliant UUID

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Introduce an RFC 4122 compliant UUID for the GPUs derived
from the unique GPU serial number (from Vega10) on gpus.
Where this serial number is not available, use a compliant
random UUID.

For virtualization, the unique ID is passed by the host driver
in the PF2VF structure.

Signed-off-by: Jiawei Gu <Jiawei.Gu@xxxxxxx>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h         | 36 ++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c  | 96 +++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c    |  4 +
 drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h |  4 +-
 drivers/gpu/drm/amd/amdgpu/nv.c             |  5 ++
 drivers/gpu/drm/amd/amdgpu/nv.h             |  3 +
 6 files changed, 146 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 3147c1c935c8..ad6d4b55be6c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -802,6 +802,40 @@ struct amd_powerplay {
 					  (rid == 0x01) || \
 					  (rid == 0x10))))
 
+union amdgpu_uuid_info {
+	struct {
+		union {
+			struct {
+				uint32_t did	: 16;
+				uint32_t fcn	: 8;
+				uint32_t asic_7 : 8;
+			};
+			uint32_t time_low;
+		};
+
+		struct {
+			uint32_t time_mid  : 16;
+			uint32_t time_high : 12;
+			uint32_t version   : 4;
+		};
+
+		struct {
+			struct {
+				uint8_t clk_seq_hi : 6;
+				uint8_t variant    : 2;
+			};
+			union {
+				uint8_t clk_seq_low;
+				uint8_t asic_6;
+			};
+			uint16_t asic_4;
+		};
+
+		uint32_t asic_0;
+	};
+	char as_char[16];
+};
+
 #define AMDGPU_RESET_MAGIC_NUM 64
 #define AMDGPU_MAX_DF_PERFMONS 4
 struct amdgpu_device {
@@ -1074,6 +1108,8 @@ struct amdgpu_device {
 	char				product_name[32];
 	char				serial[20];
 
+	union amdgpu_uuid_info uuid_info;
+
 	struct amdgpu_autodump		autodump;
 
 	atomic_t			throttling_logging_enabled;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 7c6c435e5d02..079841e1cb52 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -37,6 +37,7 @@
 #include <linux/vgaarb.h>
 #include <linux/vga_switcheroo.h>
 #include <linux/efi.h>
+#include <linux/uuid.h>
 #include "amdgpu.h"
 #include "amdgpu_trace.h"
 #include "amdgpu_i2c.h"
@@ -3239,11 +3240,104 @@ static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
 	return ret;
 }
 
+static bool amdgpu_is_uuid_info_empty(union amdgpu_uuid_info *uuid_info)
+{
+	return (uuid_info->time_low    == 0 &&
+			uuid_info->time_mid    == 0 &&
+			uuid_info->time_high   == 0 &&
+			uuid_info->version     == 0 &&
+			uuid_info->clk_seq_hi  == 0 &&
+			uuid_info->variant     == 0 &&
+			uuid_info->clk_seq_low == 0 &&
+			uuid_info->asic_4      == 0 &&
+			uuid_info->asic_0      == 0);
+}
+
+static void amdgpu_gen_uuid_info(union amdgpu_uuid_info *uuid_info,
+				uint64_t serial, uint16_t did, uint8_t idx)
+{
+	uint16_t clk_seq = 0;
+
+	/* Step1: insert clk_seq */
+	uuid_info->clk_seq_low = (uint8_t)clk_seq;
+	uuid_info->clk_seq_hi  = (uint8_t)(clk_seq >> 8) & 0x3F;
+
+	/* Step2: insert did */
+	uuid_info->did = did;
+
+	/* Step3: insert vf idx */
+	uuid_info->fcn = idx;
+
+	/* Step4: insert serial */
+	uuid_info->asic_0 = (uint32_t)serial;
+	uuid_info->asic_4 = (uint16_t)(serial >> 4 * 8) & 0xFFFF;
+	uuid_info->asic_6 = (uint8_t)(serial >> 6 * 8) & 0xFF;
+	uuid_info->asic_7 = (uint8_t)(serial >> 7 * 8) & 0xFF;
+
+	/* Step5: insert version */
+	uuid_info->version = 1;
+	/* Step6: insert variant */
+	uuid_info->variant = 2;
+}
+
+/* byte reverse random uuid */
+static void amdgpu_gen_uuid_random(union amdgpu_uuid_info *uuid_info)
+{
+	char b0, b1;
+	int i;
+
+	generate_random_uuid(uuid_info->as_char);
+	for (i = 0; i < 8; i++) {
+		b0 = uuid_info->as_char[i];
+		b1 = uuid_info->as_char[16-i];
+		uuid_info->as_char[16-i] = b0;
+		uuid_info->as_char[i] = b1;
+	}
+}
+
+/**
+ *
+ * The amdgpu driver provides a sysfs API for providing uuid data.
+ * The file uuid_info is used for this, and returns string of amdgpu uuid.
+ */
+static ssize_t amdgpu_get_uuid_info(struct device *dev,
+				      struct device_attribute *attr,
+				      char *buf)
+{
+	struct drm_device *ddev = dev_get_drvdata(dev);
+	struct amdgpu_device *adev = drm_to_adev(ddev);//ddev->dev_private;
+	union amdgpu_uuid_info *uuid = &adev->uuid_info;
+
+	return sysfs_emit(buf,
+					"%08x-%04x-%x%03x-%02x%02x-%04x%08x\n",
+					uuid->time_low,
+					uuid->time_mid,
+					uuid->version,
+					uuid->time_high,
+					uuid->clk_seq_hi |
+					uuid->variant << 6,
+					uuid->clk_seq_low,
+					uuid->asic_4,
+					uuid->asic_0);
+}
+static DEVICE_ATTR(uuid_info, S_IRUGO, amdgpu_get_uuid_info, NULL);
+
+static void amdgpu_uuid_init(struct amdgpu_device *adev)
+{
+	if (amdgpu_is_uuid_info_empty(&adev->uuid_info)) {
+		if (adev->unique_id)
+			amdgpu_gen_uuid_info(&adev->uuid_info, adev->unique_id, adev->pdev->device, 31);
+		else
+			amdgpu_gen_uuid_random(&adev->uuid_info);
+	}
+}
+
 static const struct attribute *amdgpu_dev_attributes[] = {
 	&dev_attr_product_name.attr,
 	&dev_attr_product_number.attr,
 	&dev_attr_serial_number.attr,
 	&dev_attr_pcie_replay_count.attr,
+	&dev_attr_uuid_info.attr,
 	NULL
 };
 
@@ -3551,6 +3645,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
 
 	amdgpu_fbdev_init(adev);
 
+	amdgpu_uuid_init(adev);
+
 	r = amdgpu_pm_sysfs_init(adev);
 	if (r) {
 		adev->pm_sysfs_en = false;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
index b71dd1deeb2d..2dfebfe38079 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -429,6 +429,7 @@ static void amdgpu_virt_add_bad_page(struct amdgpu_device *adev,
 static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
 {
 	struct amd_sriov_msg_pf2vf_info_header *pf2vf_info = adev->virt.fw_reserve.p_pf2vf;
+	union amdgpu_uuid_info *uuid = &adev->uuid_info;
 	uint32_t checksum;
 	uint32_t checkval;
 
@@ -498,6 +499,9 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
 
 		adev->unique_id =
 			((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->uuid;
+
+		memcpy(uuid, &((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->uuid_info_reserved,
+			sizeof(union amdgpu_uuid_info));
 		break;
 	default:
 		DRM_ERROR("invalid pf2vf version\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
index a434c71fde8e..0d1d36e82aeb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
@@ -203,9 +203,9 @@ struct amd_sriov_msg_pf2vf_info {
 		uint32_t encode_max_frame_pixels;
 	} mm_bw_management[AMD_SRIOV_MSG_RESERVE_VCN_INST];
 	/* UUID info */
-	struct amd_sriov_msg_uuid_info uuid_info;
+	uint32_t uuid_info_reserved[4];
 	/* reserved */
-	uint32_t reserved[256 - 47];
+	uint32_t reserved[256-47];
 };
 
 struct amd_sriov_msg_vf2pf_info_header {
diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
index 32c34470404c..16d4a480f4c0 100644
--- a/drivers/gpu/drm/amd/amdgpu/nv.c
+++ b/drivers/gpu/drm/amd/amdgpu/nv.c
@@ -1167,6 +1167,11 @@ static int nv_common_early_init(void *handle)
 		if (amdgpu_sriov_vf(adev))
 			adev->rev_id = 0;
 		adev->external_rev_id = adev->rev_id + 0xa;
+		if (!amdgpu_sriov_vf(adev)) {
+			adev->unique_id = RREG32(mmFUSE_DATA_730);
+			adev->unique_id <<= 32;
+			adev->unique_id |= RREG32(mmFUSE_DATA_729);
+		}
 		break;
 	case CHIP_SIENNA_CICHLID:
 		adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
diff --git a/drivers/gpu/drm/amd/amdgpu/nv.h b/drivers/gpu/drm/amd/amdgpu/nv.h
index 515d67bf249f..520ac2b98744 100644
--- a/drivers/gpu/drm/amd/amdgpu/nv.h
+++ b/drivers/gpu/drm/amd/amdgpu/nv.h
@@ -26,6 +26,9 @@
 
 #include "nbio_v2_3.h"
 
+#define mmFUSE_DATA_729 (0x176D9)
+#define mmFUSE_DATA_730 (0x176DA)
+
 void nv_grbm_select(struct amdgpu_device *adev,
 		    u32 me, u32 pipe, u32 queue, u32 vmid);
 void nv_set_virt_ops(struct amdgpu_device *adev);
-- 
2.17.1

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



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux