diff options
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 75 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 178 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 6 |
4 files changed, 262 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 1f793eb301ef..9cdaba4af216 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | |||
@@ -2300,6 +2300,9 @@ int amdgpu_device_init(struct amdgpu_device *adev, | |||
2300 | if (r) | 2300 | if (r) |
2301 | DRM_ERROR("ib ring test failed (%d).\n", r); | 2301 | DRM_ERROR("ib ring test failed (%d).\n", r); |
2302 | 2302 | ||
2303 | if (amdgpu_sriov_vf(adev)) | ||
2304 | amdgpu_virt_init_data_exchange(adev); | ||
2305 | |||
2303 | amdgpu_fbdev_init(adev); | 2306 | amdgpu_fbdev_init(adev); |
2304 | 2307 | ||
2305 | r = amdgpu_pm_sysfs_init(adev); | 2308 | r = amdgpu_pm_sysfs_init(adev); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index ab05121b9272..ed7be2eb24b0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | |||
@@ -274,3 +274,78 @@ void amdgpu_virt_free_mm_table(struct amdgpu_device *adev) | |||
274 | (void *)&adev->virt.mm_table.cpu_addr); | 274 | (void *)&adev->virt.mm_table.cpu_addr); |
275 | adev->virt.mm_table.gpu_addr = 0; | 275 | adev->virt.mm_table.gpu_addr = 0; |
276 | } | 276 | } |
277 | |||
278 | |||
279 | int amdgpu_virt_fw_reserve_get_checksum(void *obj, | ||
280 | unsigned long obj_size, | ||
281 | unsigned int key, | ||
282 | unsigned int chksum) | ||
283 | { | ||
284 | unsigned int ret = key; | ||
285 | unsigned long i = 0; | ||
286 | unsigned char *pos; | ||
287 | |||
288 | pos = (char *)obj; | ||
289 | /* calculate checksum */ | ||
290 | for (i = 0; i < obj_size; ++i) | ||
291 | ret += *(pos + i); | ||
292 | /* minus the chksum itself */ | ||
293 | pos = (char *)&chksum; | ||
294 | for (i = 0; i < sizeof(chksum); ++i) | ||
295 | ret -= *(pos + i); | ||
296 | return ret; | ||
297 | } | ||
298 | |||
299 | void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev) | ||
300 | { | ||
301 | uint32_t pf2vf_ver = 0; | ||
302 | uint32_t pf2vf_size = 0; | ||
303 | uint32_t checksum = 0; | ||
304 | uint32_t checkval; | ||
305 | char *str; | ||
306 | |||
307 | adev->virt.fw_reserve.p_pf2vf = NULL; | ||
308 | adev->virt.fw_reserve.p_vf2pf = NULL; | ||
309 | |||
310 | if (adev->fw_vram_usage.va != NULL) { | ||
311 | adev->virt.fw_reserve.p_pf2vf = | ||
312 | (struct amdgim_pf2vf_info_header *)( | ||
313 | adev->fw_vram_usage.va + AMDGIM_DATAEXCHANGE_OFFSET); | ||
314 | pf2vf_ver = adev->virt.fw_reserve.p_pf2vf->version; | ||
315 | AMDGPU_FW_VRAM_PF2VF_READ(adev, header.size, &pf2vf_size); | ||
316 | AMDGPU_FW_VRAM_PF2VF_READ(adev, checksum, &checksum); | ||
317 | |||
318 | /* pf2vf message must be in 4K */ | ||
319 | if (pf2vf_size > 0 && pf2vf_size < 4096) { | ||
320 | checkval = amdgpu_virt_fw_reserve_get_checksum( | ||
321 | adev->virt.fw_reserve.p_pf2vf, pf2vf_size, | ||
322 | adev->virt.fw_reserve.checksum_key, checksum); | ||
323 | if (checkval == checksum) { | ||
324 | adev->virt.fw_reserve.p_vf2pf = | ||
325 | ((void *)adev->virt.fw_reserve.p_pf2vf + | ||
326 | pf2vf_size); | ||
327 | memset((void *)adev->virt.fw_reserve.p_vf2pf, 0, | ||
328 | sizeof(amdgim_vf2pf_info)); | ||
329 | AMDGPU_FW_VRAM_VF2PF_WRITE(adev, header.version, | ||
330 | AMDGPU_FW_VRAM_VF2PF_VER); | ||
331 | AMDGPU_FW_VRAM_VF2PF_WRITE(adev, header.size, | ||
332 | sizeof(amdgim_vf2pf_info)); | ||
333 | AMDGPU_FW_VRAM_VF2PF_READ(adev, driver_version, | ||
334 | &str); | ||
335 | if (THIS_MODULE->version != NULL) | ||
336 | strcpy(str, THIS_MODULE->version); | ||
337 | else | ||
338 | strcpy(str, "N/A"); | ||
339 | AMDGPU_FW_VRAM_VF2PF_WRITE(adev, driver_cert, | ||
340 | 0); | ||
341 | AMDGPU_FW_VRAM_VF2PF_WRITE(adev, checksum, | ||
342 | amdgpu_virt_fw_reserve_get_checksum( | ||
343 | adev->virt.fw_reserve.p_vf2pf, | ||
344 | pf2vf_size, | ||
345 | adev->virt.fw_reserve.checksum_key, 0)); | ||
346 | } | ||
347 | } | ||
348 | } | ||
349 | } | ||
350 | |||
351 | |||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index e5fd0ff6b29d..b89d37fc406f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | |||
@@ -58,6 +58,179 @@ struct amdgpu_virt_ops { | |||
58 | void (*trans_msg)(struct amdgpu_device *adev, u32 req, u32 data1, u32 data2, u32 data3); | 58 | void (*trans_msg)(struct amdgpu_device *adev, u32 req, u32 data1, u32 data2, u32 data3); |
59 | }; | 59 | }; |
60 | 60 | ||
61 | /* | ||
62 | * Firmware Reserve Frame buffer | ||
63 | */ | ||
64 | struct amdgpu_virt_fw_reserve { | ||
65 | struct amdgim_pf2vf_info_header *p_pf2vf; | ||
66 | struct amdgim_vf2pf_info_header *p_vf2pf; | ||
67 | unsigned int checksum_key; | ||
68 | }; | ||
69 | /* | ||
70 | * Defination between PF and VF | ||
71 | * Structures forcibly aligned to 4 to keep the same style as PF. | ||
72 | */ | ||
73 | #define AMDGIM_DATAEXCHANGE_OFFSET (64 * 1024) | ||
74 | |||
75 | #define AMDGIM_GET_STRUCTURE_RESERVED_SIZE(total, u8, u16, u32, u64) \ | ||
76 | (total - (((u8)+3) / 4 + ((u16)+1) / 2 + (u32) + (u64)*2)) | ||
77 | |||
78 | enum AMDGIM_FEATURE_FLAG { | ||
79 | /* GIM supports feature of Error log collecting */ | ||
80 | AMDGIM_FEATURE_ERROR_LOG_COLLECT = 0x1, | ||
81 | /* GIM supports feature of loading uCodes */ | ||
82 | AMDGIM_FEATURE_GIM_LOAD_UCODES = 0x2, | ||
83 | }; | ||
84 | |||
85 | struct amdgim_pf2vf_info_header { | ||
86 | /* the total structure size in byte. */ | ||
87 | uint32_t size; | ||
88 | /* version of this structure, written by the GIM */ | ||
89 | uint32_t version; | ||
90 | } __aligned(4); | ||
91 | struct amdgim_pf2vf_info_v1 { | ||
92 | /* header contains size and version */ | ||
93 | struct amdgim_pf2vf_info_header header; | ||
94 | /* max_width * max_height */ | ||
95 | unsigned int uvd_enc_max_pixels_count; | ||
96 | /* 16x16 pixels/sec, codec independent */ | ||
97 | unsigned int uvd_enc_max_bandwidth; | ||
98 | /* max_width * max_height */ | ||
99 | unsigned int vce_enc_max_pixels_count; | ||
100 | /* 16x16 pixels/sec, codec independent */ | ||
101 | unsigned int vce_enc_max_bandwidth; | ||
102 | /* MEC FW position in kb from the start of visible frame buffer */ | ||
103 | unsigned int mecfw_kboffset; | ||
104 | /* The features flags of the GIM driver supports. */ | ||
105 | unsigned int feature_flags; | ||
106 | /* use private key from mailbox 2 to create chueksum */ | ||
107 | unsigned int checksum; | ||
108 | } __aligned(4); | ||
109 | |||
110 | struct amdgim_pf2vf_info_v2 { | ||
111 | /* header contains size and version */ | ||
112 | struct amdgim_pf2vf_info_header header; | ||
113 | /* use private key from mailbox 2 to create chueksum */ | ||
114 | uint32_t checksum; | ||
115 | /* The features flags of the GIM driver supports. */ | ||
116 | uint32_t feature_flags; | ||
117 | /* max_width * max_height */ | ||
118 | uint32_t uvd_enc_max_pixels_count; | ||
119 | /* 16x16 pixels/sec, codec independent */ | ||
120 | uint32_t uvd_enc_max_bandwidth; | ||
121 | /* max_width * max_height */ | ||
122 | uint32_t vce_enc_max_pixels_count; | ||
123 | /* 16x16 pixels/sec, codec independent */ | ||
124 | uint32_t vce_enc_max_bandwidth; | ||
125 | /* MEC FW position in kb from the start of VF visible frame buffer */ | ||
126 | uint64_t mecfw_kboffset; | ||
127 | /* MEC FW size in KB */ | ||
128 | uint32_t mecfw_ksize; | ||
129 | /* UVD FW position in kb from the start of VF visible frame buffer */ | ||
130 | uint64_t uvdfw_kboffset; | ||
131 | /* UVD FW size in KB */ | ||
132 | uint32_t uvdfw_ksize; | ||
133 | /* VCE FW position in kb from the start of VF visible frame buffer */ | ||
134 | uint64_t vcefw_kboffset; | ||
135 | /* VCE FW size in KB */ | ||
136 | uint32_t vcefw_ksize; | ||
137 | uint32_t reserved[AMDGIM_GET_STRUCTURE_RESERVED_SIZE(256, 0, 0, (9 + sizeof(struct amdgim_pf2vf_info_header)/sizeof(uint32_t)), 3)]; | ||
138 | } __aligned(4); | ||
139 | |||
140 | |||
141 | struct amdgim_vf2pf_info_header { | ||
142 | /* the total structure size in byte. */ | ||
143 | uint32_t size; | ||
144 | /*version of this structure, written by the guest */ | ||
145 | uint32_t version; | ||
146 | } __aligned(4); | ||
147 | |||
148 | struct amdgim_vf2pf_info_v1 { | ||
149 | /* header contains size and version */ | ||
150 | struct amdgim_vf2pf_info_header header; | ||
151 | /* driver version */ | ||
152 | char driver_version[64]; | ||
153 | /* driver certification, 1=WHQL, 0=None */ | ||
154 | unsigned int driver_cert; | ||
155 | /* guest OS type and version: need a define */ | ||
156 | unsigned int os_info; | ||
157 | /* in the unit of 1M */ | ||
158 | unsigned int fb_usage; | ||
159 | /* guest gfx engine usage percentage */ | ||
160 | unsigned int gfx_usage; | ||
161 | /* guest gfx engine health percentage */ | ||
162 | unsigned int gfx_health; | ||
163 | /* guest compute engine usage percentage */ | ||
164 | unsigned int compute_usage; | ||
165 | /* guest compute engine health percentage */ | ||
166 | unsigned int compute_health; | ||
167 | /* guest vce engine usage percentage. 0xffff means N/A. */ | ||
168 | unsigned int vce_enc_usage; | ||
169 | /* guest vce engine health percentage. 0xffff means N/A. */ | ||
170 | unsigned int vce_enc_health; | ||
171 | /* guest uvd engine usage percentage. 0xffff means N/A. */ | ||
172 | unsigned int uvd_enc_usage; | ||
173 | /* guest uvd engine usage percentage. 0xffff means N/A. */ | ||
174 | unsigned int uvd_enc_health; | ||
175 | unsigned int checksum; | ||
176 | } __aligned(4); | ||
177 | |||
178 | struct amdgim_vf2pf_info_v2 { | ||
179 | /* header contains size and version */ | ||
180 | struct amdgim_vf2pf_info_header header; | ||
181 | uint32_t checksum; | ||
182 | /* driver version */ | ||
183 | uint8_t driver_version[64]; | ||
184 | /* driver certification, 1=WHQL, 0=None */ | ||
185 | uint32_t driver_cert; | ||
186 | /* guest OS type and version: need a define */ | ||
187 | uint32_t os_info; | ||
188 | /* in the unit of 1M */ | ||
189 | uint32_t fb_usage; | ||
190 | /* guest gfx engine usage percentage */ | ||
191 | uint32_t gfx_usage; | ||
192 | /* guest gfx engine health percentage */ | ||
193 | uint32_t gfx_health; | ||
194 | /* guest compute engine usage percentage */ | ||
195 | uint32_t compute_usage; | ||
196 | /* guest compute engine health percentage */ | ||
197 | uint32_t compute_health; | ||
198 | /* guest vce engine usage percentage. 0xffff means N/A. */ | ||
199 | uint32_t vce_enc_usage; | ||
200 | /* guest vce engine health percentage. 0xffff means N/A. */ | ||
201 | uint32_t vce_enc_health; | ||
202 | /* guest uvd engine usage percentage. 0xffff means N/A. */ | ||
203 | uint32_t uvd_enc_usage; | ||
204 | /* guest uvd engine usage percentage. 0xffff means N/A. */ | ||
205 | uint32_t uvd_enc_health; | ||
206 | uint32_t reserved[AMDGIM_GET_STRUCTURE_RESERVED_SIZE(256, 64, 0, (12 + sizeof(struct amdgim_vf2pf_info_header)/sizeof(uint32_t)), 0)]; | ||
207 | } __aligned(4); | ||
208 | |||
209 | #define AMDGPU_FW_VRAM_VF2PF_VER 2 | ||
210 | typedef struct amdgim_vf2pf_info_v2 amdgim_vf2pf_info ; | ||
211 | |||
212 | #define AMDGPU_FW_VRAM_VF2PF_WRITE(adev, field, val) \ | ||
213 | do { \ | ||
214 | ((amdgim_vf2pf_info *)adev->virt.fw_reserve.p_vf2pf)->field = (val); \ | ||
215 | } while (0) | ||
216 | |||
217 | #define AMDGPU_FW_VRAM_VF2PF_READ(adev, field, val) \ | ||
218 | do { \ | ||
219 | (*val) = ((amdgim_vf2pf_info *)adev->virt.fw_reserve.p_vf2pf)->field; \ | ||
220 | } while (0) | ||
221 | |||
222 | #define AMDGPU_FW_VRAM_PF2VF_READ(adev, field, val) \ | ||
223 | do { \ | ||
224 | if (!adev->virt.fw_reserve.p_pf2vf) \ | ||
225 | *(val) = 0; \ | ||
226 | else { \ | ||
227 | if (adev->virt.fw_reserve.p_pf2vf->version == 1) \ | ||
228 | *(val) = ((struct amdgim_pf2vf_info_v1 *)adev->virt.fw_reserve.p_pf2vf)->field; \ | ||
229 | if (adev->virt.fw_reserve.p_pf2vf->version == 2) \ | ||
230 | *(val) = ((struct amdgim_pf2vf_info_v2 *)adev->virt.fw_reserve.p_pf2vf)->field; \ | ||
231 | } \ | ||
232 | } while (0) | ||
233 | |||
61 | /* GPU virtualization */ | 234 | /* GPU virtualization */ |
62 | struct amdgpu_virt { | 235 | struct amdgpu_virt { |
63 | uint32_t caps; | 236 | uint32_t caps; |
@@ -72,6 +245,7 @@ struct amdgpu_virt { | |||
72 | struct amdgpu_mm_table mm_table; | 245 | struct amdgpu_mm_table mm_table; |
73 | const struct amdgpu_virt_ops *ops; | 246 | const struct amdgpu_virt_ops *ops; |
74 | struct amdgpu_vf_error_buffer vf_errors; | 247 | struct amdgpu_vf_error_buffer vf_errors; |
248 | struct amdgpu_virt_fw_reserve fw_reserve; | ||
75 | }; | 249 | }; |
76 | 250 | ||
77 | #define AMDGPU_CSA_SIZE (8 * 1024) | 251 | #define AMDGPU_CSA_SIZE (8 * 1024) |
@@ -114,5 +288,9 @@ int amdgpu_virt_reset_gpu(struct amdgpu_device *adev); | |||
114 | int amdgpu_sriov_gpu_reset(struct amdgpu_device *adev, struct amdgpu_job *job); | 288 | int amdgpu_sriov_gpu_reset(struct amdgpu_device *adev, struct amdgpu_job *job); |
115 | int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev); | 289 | int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev); |
116 | void amdgpu_virt_free_mm_table(struct amdgpu_device *adev); | 290 | void amdgpu_virt_free_mm_table(struct amdgpu_device *adev); |
291 | int amdgpu_virt_fw_reserve_get_checksum(void *obj, unsigned long obj_size, | ||
292 | unsigned int key, | ||
293 | unsigned int chksum); | ||
294 | void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev); | ||
117 | 295 | ||
118 | #endif | 296 | #endif |
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index 2812d88a8bdd..b4906d2f30d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | |||
@@ -183,6 +183,12 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev, | |||
183 | pr_err("Doesn't get READY_TO_ACCESS_GPU from pf, give up\n"); | 183 | pr_err("Doesn't get READY_TO_ACCESS_GPU from pf, give up\n"); |
184 | return r; | 184 | return r; |
185 | } | 185 | } |
186 | /* Retrieve checksum from mailbox2 */ | ||
187 | if (req == IDH_REQ_GPU_INIT_ACCESS) { | ||
188 | adev->virt.fw_reserve.checksum_key = | ||
189 | RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, | ||
190 | mmBIF_BX_PF0_MAILBOX_MSGBUF_RCV_DW2)); | ||
191 | } | ||
186 | } | 192 | } |
187 | 193 | ||
188 | return 0; | 194 | return 0; |