<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<p style="font-family:Arial;font-size:10pt;color:#008000;margin:15pt;" align="Left">
[Public]<br>
</p>
<br>
<div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
May want to update the sysfs interface as well.<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Reviewed-by: Alex Deucher <alexander.deucher@amd.com></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Chen, Guchun <Guchun.Chen@amd.com><br>
<b>Sent:</b> Thursday, February 17, 2022 11:56 PM<br>
<b>To:</b> amd-gfx@lists.freedesktop.org <amd-gfx@lists.freedesktop.org>; Deucher, Alexander <Alexander.Deucher@amd.com>; Zhang, Hawking <Hawking.Zhang@amd.com>; Koenig, Christian <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com><br>
<b>Cc:</b> Chen, Guchun <Guchun.Chen@amd.com><br>
<b>Subject:</b> [PATCH] drm/amdgpu: read harvest bit per IP data on legacy GPUs</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">Based on firmware team's input, harvest table in VBIOS does<br>
not apply well to legacy products like Navi1x, so seperate<br>
harvest mask configuration retrieve from different places.<br>
On legacy GPUs, scan harvest bit per IP data stuctures,<br>
while for newer ones, still read IP harvest info from harvest<br>
table.<br>
<br>
Signed-off-by: Guchun Chen <guchun.chen@amd.com><br>
---<br>
 drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 119 ++++++++++++++----<br>
 1 file changed, 93 insertions(+), 26 deletions(-)<br>
<br>
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c<br>
index 2506bcf36c87..2ccac1f1582f 100644<br>
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c<br>
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c<br>
@@ -385,6 +385,87 @@ static int amdgpu_discovery_validate_ip(const struct ip *ip)<br>
         return 0;<br>
 }<br>
 <br>
+static void amdgpu_discovery_read_harvest_bit_per_ip(struct amdgpu_device *adev,<br>
+                                               uint32_t *vcn_harvest_count)<br>
+{<br>
+       struct binary_header *bhdr;<br>
+       struct ip_discovery_header *ihdr;<br>
+       struct die_header *dhdr;<br>
+       struct ip *ip;<br>
+       uint16_t die_offset, ip_offset, num_dies, num_ips;<br>
+       int i, j;<br>
+<br>
+       bhdr = (struct binary_header *)adev->mman.discovery_bin;<br>
+       ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin +<br>
+                       le16_to_cpu(bhdr->table_list[IP_DISCOVERY].offset));<br>
+       num_dies = le16_to_cpu(ihdr->num_dies);<br>
+<br>
+       /* scan harvest bit of all IP data structures */<br>
+       for (i = 0; i < num_dies; i++) {<br>
+               die_offset = le16_to_cpu(ihdr->die_info[i].die_offset);<br>
+               dhdr = (struct die_header *)(adev->mman.discovery_bin + die_offset);<br>
+               num_ips = le16_to_cpu(dhdr->num_ips);<br>
+               ip_offset = die_offset + sizeof(*dhdr);<br>
+<br>
+               for (j = 0; j < num_ips; j++) {<br>
+                       ip = (struct ip *)(adev->mman.discovery_bin + ip_offset);<br>
+<br>
+                       if (amdgpu_discovery_validate_ip(ip))<br>
+                               goto next_ip;<br>
+<br>
+                       if (le16_to_cpu(ip->harvest) == 1) {<br>
+                               switch (le16_to_cpu(ip->hw_id)) {<br>
+                               case VCN_HWID:<br>
+                                       (*vcn_harvest_count)++;<br>
+                                       if (ip->number_instance == 0)<br>
+                                               adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN0;<br>
+                                       else<br>
+                                               adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1;<br>
+                                       break;<br>
+                               case DMU_HWID:<br>
+                                       adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK;<br>
+                                       break;<br>
+                               default:<br>
+                                       break;<br>
+                                }<br>
+                        }<br>
+next_ip:<br>
+                       ip_offset += sizeof(*ip) + 4 * (ip->num_base_address - 1);<br>
+               }<br>
+       }<br>
+}<br>
+<br>
+static void amdgpu_disocvery_read_from_harvest_table(struct amdgpu_device *adev,<br>
+                                               uint32_t *vcn_harvest_count)<br>
+{<br>
+       struct binary_header *bhdr;<br>
+       struct harvest_table *harvest_info;<br>
+       int i;<br>
+<br>
+       bhdr = (struct binary_header *)adev->mman.discovery_bin;<br>
+       harvest_info = (struct harvest_table *)(adev->mman.discovery_bin +<br>
+                       le16_to_cpu(bhdr->table_list[HARVEST_INFO].offset));<br>
+       for (i = 0; i < 32; i++) {<br>
+               if (le16_to_cpu(harvest_info->list[i].hw_id) == 0)<br>
+                       break;<br>
+<br>
+               switch (le16_to_cpu(harvest_info->list[i].hw_id)) {<br>
+               case VCN_HWID:<br>
+                       (*vcn_harvest_count)++;<br>
+                       if (harvest_info->list[i].number_instance == 0)<br>
+                               adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN0;<br>
+                       else<br>
+                               adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1;<br>
+                       break;<br>
+               case DMU_HWID:<br>
+                       adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK;<br>
+                       break;<br>
+               default:<br>
+                       break;<br>
+               }<br>
+       }<br>
+}<br>
+<br>
 /* ================================================== */<br>
 <br>
 struct ip_hw_instance {<br>
@@ -1046,33 +1127,19 @@ int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, int n<br>
 <br>
 void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)<br>
 {<br>
-       struct binary_header *bhdr;<br>
-       struct harvest_table *harvest_info;<br>
-       int i, vcn_harvest_count = 0;<br>
-<br>
-       bhdr = (struct binary_header *)adev->mman.discovery_bin;<br>
-       harvest_info = (struct harvest_table *)(adev->mman.discovery_bin +<br>
-                       le16_to_cpu(bhdr->table_list[HARVEST_INFO].offset));<br>
-<br>
-       for (i = 0; i < 32; i++) {<br>
-               if (le16_to_cpu(harvest_info->list[i].hw_id) == 0)<br>
-                       break;<br>
+       int vcn_harvest_count = 0;<br>
 <br>
-               switch (le16_to_cpu(harvest_info->list[i].hw_id)) {<br>
-               case VCN_HWID:<br>
-                       vcn_harvest_count++;<br>
-                       if (harvest_info->list[i].number_instance == 0)<br>
-                               adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN0;<br>
-                       else<br>
-                               adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1;<br>
-                       break;<br>
-               case DMU_HWID:<br>
-                       adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK;<br>
-                       break;<br>
-               default:<br>
-                       break;<br>
-               }<br>
-       }<br>
+       /*<br>
+        * Harvest table does not fit Navi1x and legacy GPUs,<br>
+        * so read harvest bit per IP data structure to set<br>
+        * harvest configuration.<br>
+        */<br>
+       if (adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 2, 0))<br>
+               amdgpu_discovery_read_harvest_bit_per_ip(adev,<br>
+                                                       &vcn_harvest_count);<br>
+       else<br>
+               amdgpu_disocvery_read_from_harvest_table(adev,<br>
+                                                       &vcn_harvest_count);<br>
 <br>
         amdgpu_discovery_harvest_config_quirk(adev);<br>
 <br>
-- <br>
2.17.1<br>
<br>
</div>
</span></font></div>
</div>
</body>
</html>