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" | |
5183411b | 26 | #include "amdgpu_xgmi.h" |
fb30fc59 SL |
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 | ||
fb30fc59 SL |
34 | static struct amdgpu_hive_info xgmi_hives[AMDGPU_MAX_XGMI_HIVE]; |
35 | static unsigned hive_count = 0; | |
36 | ||
ed2bf522 AG |
37 | |
38 | void *amdgpu_xgmi_hive_try_lock(struct amdgpu_hive_info *hive) | |
39 | { | |
40 | return &hive->device_list; | |
41 | } | |
42 | ||
5183411b | 43 | struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev) |
fb30fc59 SL |
44 | { |
45 | int i; | |
46 | struct amdgpu_hive_info *tmp; | |
47 | ||
48 | if (!adev->gmc.xgmi.hive_id) | |
49 | return NULL; | |
50 | for (i = 0 ; i < hive_count; ++i) { | |
51 | tmp = &xgmi_hives[i]; | |
52 | if (tmp->hive_id == adev->gmc.xgmi.hive_id) | |
53 | return tmp; | |
54 | } | |
55 | if (i >= AMDGPU_MAX_XGMI_HIVE) | |
56 | return NULL; | |
57 | ||
58 | /* initialize new hive if not exist */ | |
59 | tmp = &xgmi_hives[hive_count++]; | |
60 | tmp->hive_id = adev->gmc.xgmi.hive_id; | |
61 | INIT_LIST_HEAD(&tmp->device_list); | |
ed2bf522 AG |
62 | mutex_init(&tmp->hive_lock); |
63 | ||
fb30fc59 SL |
64 | return tmp; |
65 | } | |
66 | ||
5183411b AG |
67 | int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev) |
68 | { | |
69 | int ret = -EINVAL; | |
70 | ||
71 | /* Each psp need to set the latest topology */ | |
72 | ret = psp_xgmi_set_topology_info(&adev->psp, | |
73 | hive->number_devices, | |
74 | &hive->topology_info); | |
75 | if (ret) | |
76 | dev_err(adev->dev, | |
77 | "XGMI: Set topology failure on device %llx, hive %llx, ret %d", | |
78 | adev->gmc.xgmi.node_id, | |
79 | adev->gmc.xgmi.hive_id, ret); | |
80 | else | |
5d66ef38 | 81 | dev_info(adev->dev, "XGMI: Set topology for node %d, hive 0x%llx.\n", |
5183411b AG |
82 | adev->gmc.xgmi.physical_node_id, |
83 | adev->gmc.xgmi.hive_id); | |
84 | ||
85 | return ret; | |
86 | } | |
87 | ||
fb30fc59 SL |
88 | int amdgpu_xgmi_add_device(struct amdgpu_device *adev) |
89 | { | |
5183411b | 90 | struct psp_xgmi_topology_info *hive_topology; |
fb30fc59 SL |
91 | struct amdgpu_hive_info *hive; |
92 | struct amdgpu_xgmi *entry; | |
5183411b | 93 | struct amdgpu_device *tmp_adev = NULL; |
fb30fc59 SL |
94 | |
95 | int count = 0, ret = -EINVAL; | |
96 | ||
47622ba0 | 97 | if (!adev->gmc.xgmi.supported) |
fb30fc59 | 98 | return 0; |
47622ba0 | 99 | |
dd3c45d3 | 100 | adev->gmc.xgmi.node_id = psp_xgmi_get_node_id(&adev->psp); |
fb30fc59 SL |
101 | adev->gmc.xgmi.hive_id = psp_xgmi_get_hive_id(&adev->psp); |
102 | ||
fb30fc59 SL |
103 | mutex_lock(&xgmi_mutex); |
104 | hive = amdgpu_get_xgmi_hive(adev); | |
105 | if (!hive) | |
106 | goto exit; | |
107 | ||
5183411b AG |
108 | hive_topology = &hive->topology_info; |
109 | ||
fb30fc59 SL |
110 | list_add_tail(&adev->gmc.xgmi.head, &hive->device_list); |
111 | list_for_each_entry(entry, &hive->device_list, head) | |
5183411b AG |
112 | hive_topology->nodes[count++].node_id = entry->node_id; |
113 | hive->number_devices = count; | |
fb30fc59 | 114 | |
a82c1566 | 115 | /* Each psp need to get the latest topology */ |
116 | list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { | |
5183411b | 117 | ret = psp_xgmi_get_topology_info(&tmp_adev->psp, count, hive_topology); |
a82c1566 | 118 | if (ret) { |
119 | dev_err(tmp_adev->dev, | |
120 | "XGMI: Get topology failure on device %llx, hive %llx, ret %d", | |
121 | tmp_adev->gmc.xgmi.node_id, | |
122 | tmp_adev->gmc.xgmi.hive_id, ret); | |
123 | /* To do : continue with some node failed or disable the whole hive */ | |
124 | break; | |
125 | } | |
fb30fc59 | 126 | } |
a82c1566 | 127 | |
fb30fc59 | 128 | list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { |
5183411b AG |
129 | ret = amdgpu_xgmi_update_topology(hive, tmp_adev); |
130 | if (ret) | |
fb30fc59 | 131 | break; |
fb30fc59 | 132 | } |
fb30fc59 SL |
133 | |
134 | exit: | |
135 | mutex_unlock(&xgmi_mutex); | |
136 | return ret; | |
137 | } | |
a82400b5 AG |
138 | |
139 | void amdgpu_xgmi_remove_device(struct amdgpu_device *adev) | |
140 | { | |
141 | struct amdgpu_hive_info *hive; | |
142 | ||
143 | if (!adev->gmc.xgmi.supported) | |
144 | return; | |
145 | ||
146 | mutex_lock(&xgmi_mutex); | |
147 | ||
148 | hive = amdgpu_get_xgmi_hive(adev); | |
149 | if (!hive) | |
150 | goto exit; | |
151 | ||
152 | if (!(hive->number_devices--)) | |
153 | mutex_destroy(&hive->hive_lock); | |
154 | ||
155 | exit: | |
156 | mutex_unlock(&xgmi_mutex); | |
157 | } |