Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amdgpu: get extended xgmi topology data

The TA has a limit to the amount of data that can be retrieved from
GET_TOPOLOGY. For setups that exceed this limit, the xGMI topology
needs to be re-initialized and data needs to be re-fetched from the
extended link records by setting a flag in the shared command buffer.

The number of hops and the number of links must be accumulated by the
driver. Other data points are all fetched from the first request.
Because the TA has already exceeded its link record limit, it
cannot hold bidirectional information. Otherwise the driver would
have to do more than two fetches so the driver has to reflect the
topology information in the opposite direction.

v2: squashed with internal reviewed fix

Signed-off-by: Jonathan Kim <jonathan.kim@amd.com>
Reviewed-by: Hawking Zhang <hawking.zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Jonathan Kim and committed by
Alex Deucher
44357a1b 3a6e4106

+145 -14
+83 -9
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
··· 29 29 #include "amdgpu.h" 30 30 #include "amdgpu_psp.h" 31 31 #include "amdgpu_ucode.h" 32 + #include "amdgpu_xgmi.h" 32 33 #include "soc15_common.h" 33 34 #include "psp_v3_1.h" 34 35 #include "psp_v10_0.h" ··· 1027 1026 return 0; 1028 1027 } 1029 1028 1030 - int psp_xgmi_initialize(struct psp_context *psp) 1029 + int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta) 1031 1030 { 1032 1031 struct ta_xgmi_shared_memory *xgmi_cmd; 1033 1032 int ret; ··· 1036 1035 !psp->xgmi.size_bytes || 1037 1036 !psp->xgmi.start_addr) 1038 1037 return -ENOENT; 1038 + 1039 + if (!load_ta) 1040 + goto invoke; 1039 1041 1040 1042 if (!psp->xgmi_context.initialized) { 1041 1043 ret = psp_xgmi_init_shared_buf(psp); ··· 1051 1047 if (ret) 1052 1048 return ret; 1053 1049 1050 + invoke: 1054 1051 /* Initialize XGMI session */ 1055 1052 xgmi_cmd = (struct ta_xgmi_shared_memory *)(psp->xgmi_context.xgmi_shared_buf); 1056 1053 memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); 1054 + xgmi_cmd->flag_extend_link_record = set_extended_data; 1057 1055 xgmi_cmd->cmd_id = TA_COMMAND_XGMI__INITIALIZE; 1058 1056 1059 1057 ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id); ··· 1109 1103 psp->xgmi.feature_version >= 0x2000000b; 1110 1104 } 1111 1105 1106 + /* 1107 + * Chips that support extended topology information require the driver to 1108 + * reflect topology information in the opposite direction. This is 1109 + * because the TA has already exceeded its link record limit and if the 1110 + * TA holds bi-directional information, the driver would have to do 1111 + * multiple fetches instead of just two. 1112 + */ 1113 + static void psp_xgmi_reflect_topology_info(struct psp_context *psp, 1114 + struct psp_xgmi_node_info node_info) 1115 + { 1116 + struct amdgpu_device *mirror_adev; 1117 + struct amdgpu_hive_info *hive; 1118 + uint64_t src_node_id = psp->adev->gmc.xgmi.node_id; 1119 + uint64_t dst_node_id = node_info.node_id; 1120 + uint8_t dst_num_hops = node_info.num_hops; 1121 + uint8_t dst_num_links = node_info.num_links; 1122 + 1123 + hive = amdgpu_get_xgmi_hive(psp->adev); 1124 + list_for_each_entry(mirror_adev, &hive->device_list, gmc.xgmi.head) { 1125 + struct psp_xgmi_topology_info *mirror_top_info; 1126 + int j; 1127 + 1128 + if (mirror_adev->gmc.xgmi.node_id != dst_node_id) 1129 + continue; 1130 + 1131 + mirror_top_info = &mirror_adev->psp.xgmi_context.top_info; 1132 + for (j = 0; j < mirror_top_info->num_nodes; j++) { 1133 + if (mirror_top_info->nodes[j].node_id != src_node_id) 1134 + continue; 1135 + 1136 + mirror_top_info->nodes[j].num_hops = dst_num_hops; 1137 + /* 1138 + * prevent 0 num_links value re-reflection since reflection 1139 + * criteria is based on num_hops (direct or indirect). 1140 + * 1141 + */ 1142 + if (dst_num_links) 1143 + mirror_top_info->nodes[j].num_links = dst_num_links; 1144 + 1145 + break; 1146 + } 1147 + 1148 + break; 1149 + } 1150 + } 1151 + 1112 1152 int psp_xgmi_get_topology_info(struct psp_context *psp, 1113 1153 int number_devices, 1114 - struct psp_xgmi_topology_info *topology) 1154 + struct psp_xgmi_topology_info *topology, 1155 + bool get_extended_data) 1115 1156 { 1116 1157 struct ta_xgmi_shared_memory *xgmi_cmd; 1117 1158 struct ta_xgmi_cmd_get_topology_info_input *topology_info_input; ··· 1171 1118 1172 1119 xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf; 1173 1120 memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); 1121 + xgmi_cmd->flag_extend_link_record = get_extended_data; 1174 1122 1175 1123 /* Fill in the shared memory with topology information as input */ 1176 1124 topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info; ··· 1194 1140 topology_info_output = &xgmi_cmd->xgmi_out_message.get_topology_info; 1195 1141 topology->num_nodes = xgmi_cmd->xgmi_out_message.get_topology_info.num_nodes; 1196 1142 for (i = 0; i < topology->num_nodes; i++) { 1197 - topology->nodes[i].node_id = topology_info_output->nodes[i].node_id; 1198 - topology->nodes[i].num_hops = topology_info_output->nodes[i].num_hops; 1199 - topology->nodes[i].is_sharing_enabled = topology_info_output->nodes[i].is_sharing_enabled; 1200 - topology->nodes[i].sdma_engine = topology_info_output->nodes[i].sdma_engine; 1143 + /* extended data will either be 0 or equal to non-extended data */ 1144 + if (topology_info_output->nodes[i].num_hops) 1145 + topology->nodes[i].num_hops = topology_info_output->nodes[i].num_hops; 1146 + 1147 + /* non-extended data gets everything here so no need to update */ 1148 + if (!get_extended_data) { 1149 + topology->nodes[i].node_id = topology_info_output->nodes[i].node_id; 1150 + topology->nodes[i].is_sharing_enabled = 1151 + topology_info_output->nodes[i].is_sharing_enabled; 1152 + topology->nodes[i].sdma_engine = 1153 + topology_info_output->nodes[i].sdma_engine; 1154 + } 1155 + 1201 1156 } 1202 1157 1203 1158 /* Invoke xgmi ta again to get the link information */ ··· 1221 1158 return ret; 1222 1159 1223 1160 link_info_output = &xgmi_cmd->xgmi_out_message.get_link_info; 1224 - for (i = 0; i < topology->num_nodes; i++) 1225 - topology->nodes[i].num_links = 1161 + for (i = 0; i < topology->num_nodes; i++) { 1162 + /* accumulate num_links on extended data */ 1163 + topology->nodes[i].num_links = get_extended_data ? 1164 + topology->nodes[i].num_links + 1165 + link_info_output->nodes[i].num_links : 1226 1166 link_info_output->nodes[i].num_links; 1167 + 1168 + /* reflect the topology information for bi-directionality */ 1169 + if (psp->xgmi_context.supports_extended_data && 1170 + get_extended_data && topology->nodes[i].num_hops) 1171 + psp_xgmi_reflect_topology_info(psp, topology->nodes[i]); 1172 + } 1227 1173 } 1228 1174 1229 1175 return 0; ··· 2889 2817 } 2890 2818 2891 2819 if (adev->gmc.xgmi.num_physical_nodes > 1) { 2892 - ret = psp_xgmi_initialize(psp); 2820 + ret = psp_xgmi_initialize(psp, false, true); 2893 2821 /* Warning the XGMI seesion initialize failure 2894 2822 * Instead of stop driver initialization 2895 2823 */ ··· 3195 3123 adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr->sos.size_bytes); 3196 3124 adev->psp.sos.start_addr = ucode_array_start_addr + 3197 3125 le32_to_cpu(sos_hdr->sos.offset_bytes); 3126 + adev->psp.xgmi_context.supports_extended_data = false; 3198 3127 } else { 3199 3128 /* Load alternate PSP SOS FW */ 3200 3129 sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data; ··· 3210 3137 adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes); 3211 3138 adev->psp.sos.start_addr = ucode_array_start_addr + 3212 3139 le32_to_cpu(sos_hdr_v1_3->sos_aux.offset_bytes); 3140 + adev->psp.xgmi_context.supports_extended_data = true; 3213 3141 } 3214 3142 3215 3143 if ((adev->psp.sys.size_bytes == 0) || (adev->psp.sos.size_bytes == 0)) {
+4 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
··· 143 143 uint64_t xgmi_shared_mc_addr; 144 144 void *xgmi_shared_buf; 145 145 struct psp_xgmi_topology_info top_info; 146 + bool supports_extended_data; 146 147 }; 147 148 148 149 struct psp_ras_context { ··· 434 433 int psp_update_vcn_sram(struct amdgpu_device *adev, int inst_idx, 435 434 uint64_t cmd_gpu_addr, int cmd_size); 436 435 437 - int psp_xgmi_initialize(struct psp_context *psp); 436 + int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta); 438 437 int psp_xgmi_terminate(struct psp_context *psp); 439 438 int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id); 440 439 int psp_xgmi_get_hive_id(struct psp_context *psp, uint64_t *hive_id); 441 440 int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id); 442 441 int psp_xgmi_get_topology_info(struct psp_context *psp, 443 442 int number_devices, 444 - struct psp_xgmi_topology_info *topology); 443 + struct psp_xgmi_topology_info *topology, 444 + bool get_extended_data); 445 445 int psp_xgmi_set_topology_info(struct psp_context *psp, 446 446 int number_devices, 447 447 struct psp_xgmi_topology_info *topology);
+56 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
··· 498 498 return -EINVAL; 499 499 } 500 500 501 + /* 502 + * Devices that support extended data require the entire hive to initialize with 503 + * the shared memory buffer flag set. 504 + * 505 + * Hive locks and conditions apply - see amdgpu_xgmi_add_device 506 + */ 507 + static int amdgpu_xgmi_initialize_hive_get_data_partition(struct amdgpu_hive_info *hive, 508 + bool set_extended_data) 509 + { 510 + struct amdgpu_device *tmp_adev; 511 + int ret; 512 + 513 + list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { 514 + ret = psp_xgmi_initialize(&tmp_adev->psp, set_extended_data, false); 515 + if (ret) { 516 + dev_err(tmp_adev->dev, 517 + "XGMI: Failed to initialize xgmi session for data partition %i\n", 518 + set_extended_data); 519 + return ret; 520 + } 521 + 522 + } 523 + 524 + return 0; 525 + } 526 + 501 527 int amdgpu_xgmi_add_device(struct amdgpu_device *adev) 502 528 { 503 529 struct psp_xgmi_topology_info *top_info; ··· 538 512 539 513 if (!adev->gmc.xgmi.pending_reset && 540 514 amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_PSP)) { 541 - ret = psp_xgmi_initialize(&adev->psp); 515 + ret = psp_xgmi_initialize(&adev->psp, false, true); 542 516 if (ret) { 543 517 dev_err(adev->dev, 544 518 "XGMI: Failed to initialize xgmi session\n"); ··· 601 575 /* get latest topology info for each device from psp */ 602 576 list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { 603 577 ret = psp_xgmi_get_topology_info(&tmp_adev->psp, count, 604 - &tmp_adev->psp.xgmi_context.top_info); 578 + &tmp_adev->psp.xgmi_context.top_info, false); 605 579 if (ret) { 606 580 dev_err(tmp_adev->dev, 607 581 "XGMI: Get topology failure on device %llx, hive %llx, ret %d", ··· 610 584 /* To do : continue with some node failed or disable the whole hive */ 611 585 goto exit_unlock; 612 586 } 587 + } 588 + 589 + /* get topology again for hives that support extended data */ 590 + if (adev->psp.xgmi_context.supports_extended_data) { 591 + 592 + /* initialize the hive to get extended data. */ 593 + ret = amdgpu_xgmi_initialize_hive_get_data_partition(hive, true); 594 + if (ret) 595 + goto exit_unlock; 596 + 597 + /* get the extended data. */ 598 + list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { 599 + ret = psp_xgmi_get_topology_info(&tmp_adev->psp, count, 600 + &tmp_adev->psp.xgmi_context.top_info, true); 601 + if (ret) { 602 + dev_err(tmp_adev->dev, 603 + "XGMI: Get topology for extended data failure on device %llx, hive %llx, ret %d", 604 + tmp_adev->gmc.xgmi.node_id, 605 + tmp_adev->gmc.xgmi.hive_id, ret); 606 + goto exit_unlock; 607 + } 608 + } 609 + 610 + /* initialize the hive to get non-extended data for the next round. */ 611 + ret = amdgpu_xgmi_initialize_hive_get_data_partition(hive, false); 612 + if (ret) 613 + goto exit_unlock; 614 + 613 615 } 614 616 } 615 617
+2 -1
drivers/gpu/drm/amd/amdgpu/ta_xgmi_if.h
··· 134 134 uint32_t cmd_id; 135 135 uint32_t resp_id; 136 136 enum ta_xgmi_status xgmi_status; 137 - uint32_t reserved; 137 + uint8_t flag_extend_link_record; 138 + uint8_t reserved0[3]; 138 139 union ta_xgmi_cmd_input xgmi_in_message; 139 140 union ta_xgmi_cmd_output xgmi_out_message; 140 141 };