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

drm/amdgpu: Add SRIOV mailbox backend for Navi1x

Mimic the ones for Vega10, add mailbox backend for Navi1x

Reviewed-by: Emily Deng <Emily.Deng@amd.com>
Signed-off-by: Jiange Zhao <Jiange.Zhao@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Jiange Zhao and committed by
Alex Deucher
3636169c 1a3f2e8c

+422 -1
+1 -1
drivers/gpu/drm/amd/amdgpu/Makefile
··· 68 68 amdgpu-y += \ 69 69 vi.o mxgpu_vi.o nbio_v6_1.o soc15.o emu_soc.o mxgpu_ai.o nbio_v7_0.o vega10_reg_init.o \ 70 70 vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o navi10_reg_init.o navi14_reg_init.o \ 71 - arct_reg_init.o navi12_reg_init.o 71 + arct_reg_init.o navi12_reg_init.o mxgpu_nv.o 72 72 73 73 # add DF block 74 74 amdgpu-y += \
+380
drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c
··· 1 + /* 2 + * Copyright 2014 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 "amdgpu.h" 25 + #include "nbio/nbio_2_3_offset.h" 26 + #include "nbio/nbio_2_3_sh_mask.h" 27 + #include "gc/gc_10_1_0_offset.h" 28 + #include "gc/gc_10_1_0_sh_mask.h" 29 + #include "soc15.h" 30 + #include "navi10_ih.h" 31 + #include "soc15_common.h" 32 + #include "mxgpu_nv.h" 33 + #include "mxgpu_ai.h" 34 + 35 + static void xgpu_nv_mailbox_send_ack(struct amdgpu_device *adev) 36 + { 37 + WREG8(NV_MAIBOX_CONTROL_RCV_OFFSET_BYTE, 2); 38 + } 39 + 40 + static void xgpu_nv_mailbox_set_valid(struct amdgpu_device *adev, bool val) 41 + { 42 + WREG8(NV_MAIBOX_CONTROL_TRN_OFFSET_BYTE, val ? 1 : 0); 43 + } 44 + 45 + /* 46 + * this peek_msg could *only* be called in IRQ routine becuase in IRQ routine 47 + * RCV_MSG_VALID filed of BIF_BX_PF_MAILBOX_CONTROL must already be set to 1 48 + * by host. 49 + * 50 + * if called no in IRQ routine, this peek_msg cannot guaranteed to return the 51 + * correct value since it doesn't return the RCV_DW0 under the case that 52 + * RCV_MSG_VALID is set by host. 53 + */ 54 + static enum idh_event xgpu_nv_mailbox_peek_msg(struct amdgpu_device *adev) 55 + { 56 + return RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, 57 + mmBIF_BX_PF_MAILBOX_MSGBUF_RCV_DW0)); 58 + } 59 + 60 + 61 + static int xgpu_nv_mailbox_rcv_msg(struct amdgpu_device *adev, 62 + enum idh_event event) 63 + { 64 + u32 reg; 65 + 66 + reg = RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, 67 + mmBIF_BX_PF_MAILBOX_MSGBUF_RCV_DW0)); 68 + if (reg != event) 69 + return -ENOENT; 70 + 71 + xgpu_nv_mailbox_send_ack(adev); 72 + 73 + return 0; 74 + } 75 + 76 + static uint8_t xgpu_nv_peek_ack(struct amdgpu_device *adev) 77 + { 78 + return RREG8(NV_MAIBOX_CONTROL_TRN_OFFSET_BYTE) & 2; 79 + } 80 + 81 + static int xgpu_nv_poll_ack(struct amdgpu_device *adev) 82 + { 83 + int timeout = NV_MAILBOX_POLL_ACK_TIMEDOUT; 84 + u8 reg; 85 + 86 + do { 87 + reg = RREG8(NV_MAIBOX_CONTROL_TRN_OFFSET_BYTE); 88 + if (reg & 2) 89 + return 0; 90 + 91 + mdelay(5); 92 + timeout -= 5; 93 + } while (timeout > 1); 94 + 95 + pr_err("Doesn't get TRN_MSG_ACK from pf in %d msec\n", NV_MAILBOX_POLL_ACK_TIMEDOUT); 96 + 97 + return -ETIME; 98 + } 99 + 100 + static int xgpu_nv_poll_msg(struct amdgpu_device *adev, enum idh_event event) 101 + { 102 + int r, timeout = NV_MAILBOX_POLL_MSG_TIMEDOUT; 103 + 104 + do { 105 + r = xgpu_nv_mailbox_rcv_msg(adev, event); 106 + if (!r) 107 + return 0; 108 + 109 + msleep(10); 110 + timeout -= 10; 111 + } while (timeout > 1); 112 + 113 + pr_err("Doesn't get msg:%d from pf, error=%d\n", event, r); 114 + 115 + return -ETIME; 116 + } 117 + 118 + static void xgpu_nv_mailbox_trans_msg (struct amdgpu_device *adev, 119 + enum idh_request req, u32 data1, u32 data2, u32 data3) 120 + { 121 + u32 reg; 122 + int r; 123 + uint8_t trn; 124 + 125 + /* IMPORTANT: 126 + * clear TRN_MSG_VALID valid to clear host's RCV_MSG_ACK 127 + * and with host's RCV_MSG_ACK cleared hw automatically clear host's RCV_MSG_ACK 128 + * which lead to VF's TRN_MSG_ACK cleared, otherwise below xgpu_nv_poll_ack() 129 + * will return immediatly 130 + */ 131 + do { 132 + xgpu_nv_mailbox_set_valid(adev, false); 133 + trn = xgpu_nv_peek_ack(adev); 134 + if (trn) { 135 + pr_err("trn=%x ACK should not assert! wait again !\n", trn); 136 + msleep(1); 137 + } 138 + } while (trn); 139 + 140 + reg = RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, 141 + mmBIF_BX_PF_MAILBOX_MSGBUF_TRN_DW0)); 142 + reg = REG_SET_FIELD(reg, BIF_BX_PF_MAILBOX_MSGBUF_TRN_DW0, 143 + MSGBUF_DATA, req); 144 + WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_MSGBUF_TRN_DW0), 145 + reg); 146 + WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_MSGBUF_TRN_DW1), 147 + data1); 148 + WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_MSGBUF_TRN_DW2), 149 + data2); 150 + WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_MSGBUF_TRN_DW3), 151 + data3); 152 + 153 + xgpu_nv_mailbox_set_valid(adev, true); 154 + 155 + /* start to poll ack */ 156 + r = xgpu_nv_poll_ack(adev); 157 + if (r) 158 + pr_err("Doesn't get ack from pf, continue\n"); 159 + 160 + xgpu_nv_mailbox_set_valid(adev, false); 161 + } 162 + 163 + static int xgpu_nv_send_access_requests(struct amdgpu_device *adev, 164 + enum idh_request req) 165 + { 166 + int r; 167 + 168 + xgpu_nv_mailbox_trans_msg(adev, req, 0, 0, 0); 169 + 170 + /* start to check msg if request is idh_req_gpu_init_access */ 171 + if (req == IDH_REQ_GPU_INIT_ACCESS || 172 + req == IDH_REQ_GPU_FINI_ACCESS || 173 + req == IDH_REQ_GPU_RESET_ACCESS) { 174 + r = xgpu_nv_poll_msg(adev, IDH_READY_TO_ACCESS_GPU); 175 + if (r) { 176 + pr_err("Doesn't get READY_TO_ACCESS_GPU from pf, give up\n"); 177 + return r; 178 + } 179 + /* Retrieve checksum from mailbox2 */ 180 + if (req == IDH_REQ_GPU_INIT_ACCESS || req == IDH_REQ_GPU_RESET_ACCESS) { 181 + adev->virt.fw_reserve.checksum_key = 182 + RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, 183 + mmBIF_BX_PF_MAILBOX_MSGBUF_RCV_DW2)); 184 + } 185 + } 186 + 187 + return 0; 188 + } 189 + 190 + static int xgpu_nv_request_reset(struct amdgpu_device *adev) 191 + { 192 + return xgpu_nv_send_access_requests(adev, IDH_REQ_GPU_RESET_ACCESS); 193 + } 194 + 195 + static int xgpu_nv_request_full_gpu_access(struct amdgpu_device *adev, 196 + bool init) 197 + { 198 + enum idh_request req; 199 + 200 + req = init ? IDH_REQ_GPU_INIT_ACCESS : IDH_REQ_GPU_FINI_ACCESS; 201 + return xgpu_nv_send_access_requests(adev, req); 202 + } 203 + 204 + static int xgpu_nv_release_full_gpu_access(struct amdgpu_device *adev, 205 + bool init) 206 + { 207 + enum idh_request req; 208 + int r = 0; 209 + 210 + req = init ? IDH_REL_GPU_INIT_ACCESS : IDH_REL_GPU_FINI_ACCESS; 211 + r = xgpu_nv_send_access_requests(adev, req); 212 + 213 + return r; 214 + } 215 + 216 + static int xgpu_nv_mailbox_ack_irq(struct amdgpu_device *adev, 217 + struct amdgpu_irq_src *source, 218 + struct amdgpu_iv_entry *entry) 219 + { 220 + DRM_DEBUG("get ack intr and do nothing.\n"); 221 + return 0; 222 + } 223 + 224 + static int xgpu_nv_set_mailbox_ack_irq(struct amdgpu_device *adev, 225 + struct amdgpu_irq_src *source, 226 + unsigned type, 227 + enum amdgpu_interrupt_state state) 228 + { 229 + u32 tmp = RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_INT_CNTL)); 230 + 231 + tmp = REG_SET_FIELD(tmp, BIF_BX_PF_MAILBOX_INT_CNTL, ACK_INT_EN, 232 + (state == AMDGPU_IRQ_STATE_ENABLE) ? 1 : 0); 233 + WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_INT_CNTL), tmp); 234 + 235 + return 0; 236 + } 237 + 238 + static void xgpu_nv_mailbox_flr_work(struct work_struct *work) 239 + { 240 + struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work); 241 + struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt); 242 + int timeout = NV_MAILBOX_POLL_FLR_TIMEDOUT; 243 + int locked; 244 + 245 + /* block amdgpu_gpu_recover till msg FLR COMPLETE received, 246 + * otherwise the mailbox msg will be ruined/reseted by 247 + * the VF FLR. 248 + * 249 + * we can unlock the lock_reset to allow "amdgpu_job_timedout" 250 + * to run gpu_recover() after FLR_NOTIFICATION_CMPL received 251 + * which means host side had finished this VF's FLR. 252 + */ 253 + locked = mutex_trylock(&adev->lock_reset); 254 + if (locked) 255 + adev->in_gpu_reset = 1; 256 + 257 + do { 258 + if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) 259 + goto flr_done; 260 + 261 + msleep(10); 262 + timeout -= 10; 263 + } while (timeout > 1); 264 + 265 + flr_done: 266 + if (locked) { 267 + adev->in_gpu_reset = 0; 268 + mutex_unlock(&adev->lock_reset); 269 + } 270 + 271 + /* Trigger recovery for world switch failure if no TDR */ 272 + if (amdgpu_device_should_recover_gpu(adev)) 273 + amdgpu_device_gpu_recover(adev, NULL); 274 + } 275 + 276 + static int xgpu_nv_set_mailbox_rcv_irq(struct amdgpu_device *adev, 277 + struct amdgpu_irq_src *src, 278 + unsigned type, 279 + enum amdgpu_interrupt_state state) 280 + { 281 + u32 tmp = RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_INT_CNTL)); 282 + 283 + tmp = REG_SET_FIELD(tmp, BIF_BX_PF_MAILBOX_INT_CNTL, VALID_INT_EN, 284 + (state == AMDGPU_IRQ_STATE_ENABLE) ? 1 : 0); 285 + WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_INT_CNTL), tmp); 286 + 287 + return 0; 288 + } 289 + 290 + static int xgpu_nv_mailbox_rcv_irq(struct amdgpu_device *adev, 291 + struct amdgpu_irq_src *source, 292 + struct amdgpu_iv_entry *entry) 293 + { 294 + enum idh_event event = xgpu_nv_mailbox_peek_msg(adev); 295 + 296 + switch (event) { 297 + case IDH_FLR_NOTIFICATION: 298 + if (amdgpu_sriov_runtime(adev)) 299 + schedule_work(&adev->virt.flr_work); 300 + break; 301 + /* READY_TO_ACCESS_GPU is fetched by kernel polling, IRQ can ignore 302 + * it byfar since that polling thread will handle it, 303 + * other msg like flr complete is not handled here. 304 + */ 305 + case IDH_CLR_MSG_BUF: 306 + case IDH_FLR_NOTIFICATION_CMPL: 307 + case IDH_READY_TO_ACCESS_GPU: 308 + default: 309 + break; 310 + } 311 + 312 + return 0; 313 + } 314 + 315 + static const struct amdgpu_irq_src_funcs xgpu_nv_mailbox_ack_irq_funcs = { 316 + .set = xgpu_nv_set_mailbox_ack_irq, 317 + .process = xgpu_nv_mailbox_ack_irq, 318 + }; 319 + 320 + static const struct amdgpu_irq_src_funcs xgpu_nv_mailbox_rcv_irq_funcs = { 321 + .set = xgpu_nv_set_mailbox_rcv_irq, 322 + .process = xgpu_nv_mailbox_rcv_irq, 323 + }; 324 + 325 + void xgpu_nv_mailbox_set_irq_funcs(struct amdgpu_device *adev) 326 + { 327 + adev->virt.ack_irq.num_types = 1; 328 + adev->virt.ack_irq.funcs = &xgpu_nv_mailbox_ack_irq_funcs; 329 + adev->virt.rcv_irq.num_types = 1; 330 + adev->virt.rcv_irq.funcs = &xgpu_nv_mailbox_rcv_irq_funcs; 331 + } 332 + 333 + int xgpu_nv_mailbox_add_irq_id(struct amdgpu_device *adev) 334 + { 335 + int r; 336 + 337 + r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_BIF, 135, &adev->virt.rcv_irq); 338 + if (r) 339 + return r; 340 + 341 + r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_BIF, 138, &adev->virt.ack_irq); 342 + if (r) { 343 + amdgpu_irq_put(adev, &adev->virt.rcv_irq, 0); 344 + return r; 345 + } 346 + 347 + return 0; 348 + } 349 + 350 + int xgpu_nv_mailbox_get_irq(struct amdgpu_device *adev) 351 + { 352 + int r; 353 + 354 + r = amdgpu_irq_get(adev, &adev->virt.rcv_irq, 0); 355 + if (r) 356 + return r; 357 + r = amdgpu_irq_get(adev, &adev->virt.ack_irq, 0); 358 + if (r) { 359 + amdgpu_irq_put(adev, &adev->virt.rcv_irq, 0); 360 + return r; 361 + } 362 + 363 + INIT_WORK(&adev->virt.flr_work, xgpu_nv_mailbox_flr_work); 364 + 365 + return 0; 366 + } 367 + 368 + void xgpu_nv_mailbox_put_irq(struct amdgpu_device *adev) 369 + { 370 + amdgpu_irq_put(adev, &adev->virt.ack_irq, 0); 371 + amdgpu_irq_put(adev, &adev->virt.rcv_irq, 0); 372 + } 373 + 374 + const struct amdgpu_virt_ops xgpu_nv_virt_ops = { 375 + .req_full_gpu = xgpu_nv_request_full_gpu_access, 376 + .rel_full_gpu = xgpu_nv_release_full_gpu_access, 377 + .reset_gpu = xgpu_nv_request_reset, 378 + .wait_reset = NULL, 379 + .trans_msg = xgpu_nv_mailbox_trans_msg, 380 + };
+41
drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h
··· 1 + /* 2 + * Copyright 2014 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 + #ifndef __MXGPU_NV_H__ 25 + #define __MXGPU_NV_H__ 26 + 27 + #define NV_MAILBOX_POLL_ACK_TIMEDOUT 500 28 + #define NV_MAILBOX_POLL_MSG_TIMEDOUT 12000 29 + #define NV_MAILBOX_POLL_FLR_TIMEDOUT 500 30 + 31 + extern const struct amdgpu_virt_ops xgpu_nv_virt_ops; 32 + 33 + void xgpu_nv_mailbox_set_irq_funcs(struct amdgpu_device *adev); 34 + int xgpu_nv_mailbox_add_irq_id(struct amdgpu_device *adev); 35 + int xgpu_nv_mailbox_get_irq(struct amdgpu_device *adev); 36 + void xgpu_nv_mailbox_put_irq(struct amdgpu_device *adev); 37 + 38 + #define NV_MAIBOX_CONTROL_TRN_OFFSET_BYTE (SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_CONTROL) * 4) 39 + #define NV_MAIBOX_CONTROL_RCV_OFFSET_BYTE (SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_CONTROL) * 4 + 1) 40 + 41 + #endif