]>
Commit | Line | Data |
---|---|---|
fb30fc59 SL |
1 | /* |
2 | * Copyright 2018 Advanced Micro Devices, Inc. | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |
5 | * copy of this software and associated documentation files (the "Software"), | |
6 | * to deal in the Software without restriction, including without limitation | |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
8 | * and/or sell copies of the Software, and to permit persons to whom the | |
9 | * Software is furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
20 | * OTHER DEALINGS IN THE SOFTWARE. | |
21 | * | |
22 | * | |
23 | */ | |
24 | #include <linux/list.h> | |
25 | #include "amdgpu.h" | |
26 | #include "amdgpu_psp.h" | |
27 | ||
28 | ||
29 | static DEFINE_MUTEX(xgmi_mutex); | |
30 | ||
31 | #define AMDGPU_MAX_XGMI_HIVE 8 | |
32 | #define AMDGPU_MAX_XGMI_DEVICE_PER_HIVE 4 | |
33 | ||
34 | struct amdgpu_hive_info { | |
35 | uint64_t hive_id; | |
36 | struct list_head device_list; | |
37 | }; | |
38 | ||
39 | static struct amdgpu_hive_info xgmi_hives[AMDGPU_MAX_XGMI_HIVE]; | |
40 | static unsigned hive_count = 0; | |
41 | ||
42 | static struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev) | |
43 | { | |
44 | int i; | |
45 | struct amdgpu_hive_info *tmp; | |
46 | ||
47 | if (!adev->gmc.xgmi.hive_id) | |
48 | return NULL; | |
49 | for (i = 0 ; i < hive_count; ++i) { | |
50 | tmp = &xgmi_hives[i]; | |
51 | if (tmp->hive_id == adev->gmc.xgmi.hive_id) | |
52 | return tmp; | |
53 | } | |
54 | if (i >= AMDGPU_MAX_XGMI_HIVE) | |
55 | return NULL; | |
56 | ||
57 | /* initialize new hive if not exist */ | |
58 | tmp = &xgmi_hives[hive_count++]; | |
59 | tmp->hive_id = adev->gmc.xgmi.hive_id; | |
60 | INIT_LIST_HEAD(&tmp->device_list); | |
61 | return tmp; | |
62 | } | |
63 | ||
64 | int amdgpu_xgmi_add_device(struct amdgpu_device *adev) | |
65 | { | |
66 | struct psp_xgmi_topology_info tmp_topology[AMDGPU_MAX_XGMI_DEVICE_PER_HIVE]; | |
67 | struct amdgpu_hive_info *hive; | |
68 | struct amdgpu_xgmi *entry; | |
69 | struct amdgpu_device *tmp_adev; | |
70 | ||
71 | int count = 0, ret = -EINVAL; | |
72 | ||
73 | if ((adev->asic_type < CHIP_VEGA20) || | |
74 | (adev->flags & AMD_IS_APU) ) | |
75 | return 0; | |
76 | adev->gmc.xgmi.device_id = psp_xgmi_get_device_id(&adev->psp); | |
77 | adev->gmc.xgmi.hive_id = psp_xgmi_get_hive_id(&adev->psp); | |
78 | ||
79 | memset(&tmp_topology[0], 0, sizeof(tmp_topology)); | |
80 | mutex_lock(&xgmi_mutex); | |
81 | hive = amdgpu_get_xgmi_hive(adev); | |
82 | if (!hive) | |
83 | goto exit; | |
84 | ||
85 | list_add_tail(&adev->gmc.xgmi.head, &hive->device_list); | |
86 | list_for_each_entry(entry, &hive->device_list, head) | |
87 | tmp_topology[count++].device_id = entry->device_id; | |
88 | ||
89 | ret = psp_xgmi_get_topology_info(&adev->psp, count, tmp_topology); | |
90 | if (ret) { | |
91 | dev_err(adev->dev, | |
92 | "XGMI: Get topology failure on device %llx, hive %llx, ret %d", | |
93 | adev->gmc.xgmi.device_id, | |
94 | adev->gmc.xgmi.hive_id, ret); | |
95 | goto exit; | |
96 | } | |
97 | /* Each psp need to set the latest topology */ | |
98 | list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { | |
99 | ret = psp_xgmi_set_topology_info(&tmp_adev->psp, count, tmp_topology); | |
100 | if (ret) { | |
101 | dev_err(tmp_adev->dev, | |
102 | "XGMI: Set topology failure on device %llx, hive %llx, ret %d", | |
103 | tmp_adev->gmc.xgmi.device_id, | |
104 | tmp_adev->gmc.xgmi.hive_id, ret); | |
105 | /* To do : continue with some node failed or disable the whole hive */ | |
106 | break; | |
107 | } | |
108 | } | |
109 | if (!ret) | |
110 | dev_info(adev->dev, "XGMI: Add node %d to hive 0x%llx.\n", | |
111 | adev->gmc.xgmi.physical_node_id, | |
112 | adev->gmc.xgmi.hive_id); | |
113 | ||
114 | exit: | |
115 | mutex_unlock(&xgmi_mutex); | |
116 | return ret; | |
117 | } | |
118 | ||
119 |