1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 1993-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 /********************************* DMA Manager *****************************\
25 * *
26 * Method notifications are handled in this module. DMA report and OS *
27 * action are dealt with on a per-object basis. *
28 * *
29 ****************************************************************************/
30
31 #include "core/core.h"
32 #include "gpu/gpu.h"
33 #include "gpu/mem_mgr/virt_mem_allocator.h"
34 #include "gpu/mem_mgr/virt_mem_allocator_common.h"
35 #include "gpu/mem_mgr/context_dma.h"
36 #include "os/os.h"
37 #include "objtmr.h"
38 #include "gpu/device/device.h"
39 #include "gpu/bus/kern_bus.h"
40 #include "gpu/mem_mgr/mem_mgr.h"
41 #include "platform/sli/sli.h"
42
43 //---------------------------------------------------------------------------
44 //
45 // Notification completion.
46 //
47 //---------------------------------------------------------------------------
48
notifyMethodComplete(OBJGPU * pGpu,ChannelDescendant * pObject,NvU32 Offset,NvV32 Data,NvU32 info32,NvU16 info16,NV_STATUS CompletionStatus)49 void notifyMethodComplete
50 (
51 OBJGPU *pGpu,
52 ChannelDescendant *pObject,
53 NvU32 Offset,
54 NvV32 Data,
55 NvU32 info32,
56 NvU16 info16,
57 NV_STATUS CompletionStatus
58 )
59 {
60 if (pObject->bNotifyTrigger)
61 {
62 pObject->bNotifyTrigger = NV_FALSE;
63
64 //
65 // Do any OS specified action related to this notification.
66 //
67 if (pObject->notifyAction)
68 {
69 PEVENTNOTIFICATION pEventNotifications = inotifyGetNotificationList(staticCast(pObject, INotifier));
70 notifyEvents(pGpu, pEventNotifications, 0, Offset, Data, CompletionStatus, pObject->notifyAction);
71 }
72 }
73 }
74
notifyWriteNotifier(OBJGPU * pGpu,ContextDma * NotifyXlate,NvV32 Info32,NvV16 Info16,NV_STATUS CompletionStatus,NvU64 Offset,NvBool TimeSupplied,NvU64 Time)75 static NV_STATUS notifyWriteNotifier
76 (
77 OBJGPU *pGpu,
78 ContextDma *NotifyXlate,
79 NvV32 Info32,
80 NvV16 Info16,
81 NV_STATUS CompletionStatus,
82 NvU64 Offset,
83 NvBool TimeSupplied,
84 NvU64 Time
85 )
86 {
87 NV_STATUS status;
88 NOTIFICATION *pNotifyBuffer;
89
90 //
91 // Fill in the notification structure.
92 //
93 status = ctxdmaGetKernelVA( NotifyXlate, Offset, sizeof(*pNotifyBuffer),
94 (void **)&(pNotifyBuffer),
95 gpumgrGetSubDeviceInstanceFromGpu(gpumgrGetParentGPU(pGpu)));
96
97 if (status != NV_OK)
98 {
99 return status;
100 }
101
102 notifyFillNOTIFICATION(pGpu, pNotifyBuffer, Info32, Info16,
103 CompletionStatus, TimeSupplied, Time);
104 return status;
105 }
106
107 void
notifyFillNOTIFICATION(OBJGPU * pGpu,NOTIFICATION * pNotifyBuffer,NvV32 Info32,NvV16 Info16,NV_STATUS CompletionStatus,NvBool TimeSupplied,NvU64 Time)108 notifyFillNOTIFICATION
109 (
110 OBJGPU *pGpu,
111 NOTIFICATION *pNotifyBuffer,
112 NvV32 Info32,
113 NvV16 Info16,
114 NV_STATUS CompletionStatus,
115 NvBool TimeSupplied,
116 NvU64 Time
117 )
118 {
119 INFO16_STATUS infoStatus;
120 NvU32 TimeHi, TimeLo;
121
122 if (!TimeSupplied)
123 {
124 OBJTMR *pTmr = GPU_GET_TIMER(pGpu);
125 tmrGetCurrentTime(pTmr, &Time);
126 }
127
128 TimeLo = NvU64_LO32(Time);
129 TimeHi = NvU64_HI32(Time);
130
131 //
132 // Since notifiers are not read by the GPU, and only the CPU, these
133 // writes to not need to be flushed. A subsequent CPU read to this data
134 // will be serialized with these writes
135 //
136 MEM_WR32(&pNotifyBuffer->OtherInfo32, Info32);
137 MEM_WR32(&pNotifyBuffer->TimeHi, TimeHi);
138 MEM_WR32(&pNotifyBuffer->TimeLo, TimeLo);
139
140 //
141 // Combine into 32b write to avoid issues in environments that don't
142 // support 16b writes. For example, when routing all memory requests
143 // through IFB we are limited to 32b read/writes only.
144 //
145 infoStatus.Info16Status_16.Status = (NvV16) CompletionStatus;
146 infoStatus.Info16Status_16.OtherInfo16 = Info16;
147 MEM_WR32(&pNotifyBuffer->Info16Status.Info16Status_32,
148 infoStatus.Info16Status_32);
149 }
150
151 void
notifyFillNvNotification(OBJGPU * pGpu,NvNotification * pNotification,NvV32 Info32,NvV16 Info16,NV_STATUS CompletionStatus,NvBool TimeSupplied,NvU64 Time)152 notifyFillNvNotification
153 (
154 OBJGPU *pGpu,
155 NvNotification *pNotification,
156 NvV32 Info32,
157 NvV16 Info16,
158 NV_STATUS CompletionStatus,
159 NvBool TimeSupplied,
160 NvU64 Time
161 )
162 {
163 NvU32 TimeHi, TimeLo;
164
165 if (!TimeSupplied)
166 {
167 OBJTMR *pTmr = GPU_GET_TIMER(pGpu);
168 tmrGetCurrentTime(pTmr, &Time);
169 }
170
171 TimeLo = NvU64_LO32(Time);
172 TimeHi = NvU64_HI32(Time);
173
174 //
175 // Since notifiers are not read by the GPU, and only the CPU, these
176 // writes do not need to be flushed. A subsequent CPU read to this data
177 // will be serialized with these writes
178 //
179 MEM_WR16(&pNotification->info16, Info16);
180 MEM_WR32(&pNotification->info32, Info32);
181 MEM_WR32(&pNotification->timeStamp.nanoseconds[0], TimeHi);
182 MEM_WR32(&pNotification->timeStamp.nanoseconds[1], TimeLo);
183 MEM_WR16(&pNotification->status, CompletionStatus);
184 }
185
notifyFillNotifier(OBJGPU * pGpu,ContextDma * NotifyXlate,NvV32 Info32,NvV16 Info16,NV_STATUS CompletionStatus)186 NV_STATUS notifyFillNotifier
187 (
188 OBJGPU *pGpu,
189 ContextDma *NotifyXlate,
190 NvV32 Info32,
191 NvV16 Info16,
192 NV_STATUS CompletionStatus
193 )
194 {
195 return notifyWriteNotifier(pGpu, NotifyXlate, Info32,
196 Info16, CompletionStatus,
197 0, NV_FALSE, 0);
198 }
199
notifyFillNotifierOffsetTimestamp(OBJGPU * pGpu,ContextDma * NotifyXlate,NvV32 Info32,NvV16 Info16,NV_STATUS CompletionStatus,NvU64 Offset,NvU64 Time)200 NV_STATUS notifyFillNotifierOffsetTimestamp
201 (
202 OBJGPU *pGpu,
203 ContextDma *NotifyXlate,
204 NvV32 Info32,
205 NvV16 Info16,
206 NV_STATUS CompletionStatus,
207 NvU64 Offset,
208 NvU64 Time
209 )
210 {
211 return notifyWriteNotifier(pGpu, NotifyXlate, Info32,
212 Info16, CompletionStatus,
213 Offset,
214 NV_TRUE, Time);
215 }
216
notifyFillNotifierOffset(OBJGPU * pGpu,ContextDma * NotifyXlate,NvV32 Info32,NvV16 Info16,NV_STATUS CompletionStatus,NvU64 Offset)217 NV_STATUS notifyFillNotifierOffset
218 (
219 OBJGPU *pGpu,
220 ContextDma *NotifyXlate,
221 NvV32 Info32,
222 NvV16 Info16,
223 NV_STATUS CompletionStatus,
224 NvU64 Offset
225 )
226 {
227 return notifyWriteNotifier(pGpu, NotifyXlate, Info32,
228 Info16, CompletionStatus,
229 Offset,
230 NV_FALSE, 0);
231 }
232
notifyFillNotifierArrayTimestamp(OBJGPU * pGpu,ContextDma * NotifyXlate,NvV32 Info32,NvV16 Info16,NV_STATUS CompletionStatus,NvU32 Index,NvU64 Time)233 NV_STATUS notifyFillNotifierArrayTimestamp
234 (
235 OBJGPU *pGpu,
236 ContextDma *NotifyXlate,
237 NvV32 Info32,
238 NvV16 Info16,
239 NV_STATUS CompletionStatus,
240 NvU32 Index,
241 NvU64 Time
242 )
243 {
244 return notifyWriteNotifier(pGpu, NotifyXlate, Info32,
245 Info16, CompletionStatus,
246 Index * sizeof(NOTIFICATION),
247 NV_TRUE, Time);
248 }
249
notifyFillNotifierArray(OBJGPU * pGpu,ContextDma * NotifyXlate,NvV32 Info32,NvV16 Info16,NV_STATUS CompletionStatus,NvU32 Index)250 NV_STATUS notifyFillNotifierArray
251 (
252 OBJGPU *pGpu,
253 ContextDma *NotifyXlate,
254 NvV32 Info32,
255 NvV16 Info16,
256 NV_STATUS CompletionStatus,
257 NvU32 Index
258 )
259 {
260 return notifyWriteNotifier(pGpu, NotifyXlate, Info32,
261 Info16, CompletionStatus,
262 Index * sizeof(NOTIFICATION),
263 NV_FALSE, 0);
264 }
265
266 /*
267 * @brief fills notifier at GPU VA base + index with given info,
268 * time and completion status
269 *
270 * Looks up dma memory mapping with given GPU VA and performs writes.
271 * Notifier write is skipped when CPU kernel mapping is missing.
272 *
273 * @param[in] pGpu OBJGPU pointer
274 * @param[in] pDevice Device pointer
275 * @param[in] hMemoryCtx Handle of a memory object to which NotifyGPUVABase belongs
276 * @param[in] NotifyGPUVABase 64b GPU VA base address of semaphore
277 * @param[in] Info32 32b info part
278 * @param[in] Info16 16b info part
279 * @param[in] CompletionStatus NV_STATUS value to write to notifier status
280 * @param[in] Index index of notifier in notifier array
281 * @param[in] Time 64b time stamp
282 *
283 * @return NV_ERR_INVALID_ADDRESS on wrong GPU VA address or out of bound index,
284 * NV_OK on success
285 *
286 */
notifyFillNotifierGPUVATimestamp(OBJGPU * pGpu,Device * pDevice,NvHandle hMemoryCtx,NvU64 NotifyGPUVABase,NvV32 Info32,NvV16 Info16,NV_STATUS CompletionStatus,NvU32 Index,NvU64 Time)287 NV_STATUS notifyFillNotifierGPUVATimestamp
288 (
289 OBJGPU *pGpu,
290 Device *pDevice,
291 NvHandle hMemoryCtx,
292 NvU64 NotifyGPUVABase,
293 NvV32 Info32,
294 NvV16 Info16,
295 NV_STATUS CompletionStatus,
296 NvU32 Index,
297 NvU64 Time
298 )
299 {
300 NvU64 notifyGPUVA;
301 NvBool bFound;
302 CLI_DMA_MAPPING_INFO *pDmaMappingInfo;
303 NvU64 offset;
304 NvU32 subdeviceInstance;
305 NOTIFICATION *pNotifier;
306
307 notifyGPUVA = NotifyGPUVABase + (Index * sizeof(NOTIFICATION));
308
309 // Memory context is required for mapping lookup
310 bFound = CliGetDmaMappingInfo(RES_GET_CLIENT(pDevice),
311 RES_GET_HANDLE(pDevice),
312 hMemoryCtx,
313 notifyGPUVA,
314 gpumgrGetDeviceGpuMask(pGpu->deviceInstance),
315 &pDmaMappingInfo);
316 if (!bFound)
317 {
318 NV_PRINTF(LEVEL_ERROR, "Can't find mapping; notifier not written\n");
319 return NV_ERR_INVALID_ADDRESS;
320 }
321
322 offset = notifyGPUVA - pDmaMappingInfo->DmaOffset;
323 if ((offset + sizeof(NOTIFICATION)) > pDmaMappingInfo->pMemDesc->Size)
324 {
325 NV_PRINTF(LEVEL_ERROR,
326 "offset+size doesn't fit into mapping; notifier not written\n");
327 return NV_ERR_INVALID_ADDRESS;
328 }
329
330 //
331 // Set idx to default position in the dma mapped address array
332 //
333 subdeviceInstance = gpumgrGetSubDeviceInstanceFromGpu(gpumgrGetParentGPU(pGpu));
334
335 SLI_LOOP_START(SLI_LOOP_FLAGS_NONE)
336
337 if (IsSLIEnabled(pGpu) &&
338 (memdescGetAddressSpace(pDmaMappingInfo->pMemDesc) == ADDR_FBMEM))
339 {
340 //
341 // If SLI and it is vidmem, replace idx with appropriate SLI index
342 // otherwise, this just stays the default value.
343 //
344 subdeviceInstance = gpumgrGetSubDeviceInstanceFromGpu(pGpu);
345 }
346
347 if (!pDmaMappingInfo->KernelVAddr[subdeviceInstance])
348 {
349 NV_PRINTF(LEVEL_ERROR, "KernelVAddr==NULL; notifier not written\n");
350 }
351 else
352 {
353 pNotifier = (PNOTIFICATION)((NvU8*)pDmaMappingInfo->KernelVAddr[subdeviceInstance] + offset);
354
355 notifyFillNOTIFICATION(pGpu, pNotifier, Info32, Info16,
356 CompletionStatus, NV_TRUE, Time);
357 }
358
359 SLI_LOOP_END
360
361 return NV_OK;
362 }
363
364 /*
365 * @brief fills notifier at GPU VA base + index with current time, given info,
366 * and completion status
367 *
368 * Use this function to fill notifier through BAR1 when you have GPU VA.
369 *
370 * Wrapper for notifyFillNotifierGPUVATimestamp.
371 * Gets current time and routes data to notifyFillNotifierGPUVATimestamp
372 *
373 * @param[in] pGpu OBJGPU pointer
374 * @param[in] pDevice Device pointer
375 * @param[in] hMemoryCtx Handle of a memory object to which NotifyGPUVABase belongs
376 * @param[in] NotifyGPUVABase 64b GPU VA base address of semaphore
377 * @param[in] Info32 32b info part
378 * @param[in] Info16 16b info part
379 * @param[in] CompletionStatus NV_STATUS value to write to notifier status
380 * @param[in] Index index of notifier in notifier array
381 * @param[in] Time 64b time stamp
382 *
383 * @return status of notifyFillNotifierGPUVATimestamp
384 */
notifyFillNotifierGPUVA(OBJGPU * pGpu,Device * pDevice,NvHandle hMemoryCtx,NvU64 NotifyGPUVABase,NvV32 Info32,NvV16 Info16,NV_STATUS CompletionStatus,NvU32 Index)385 NV_STATUS notifyFillNotifierGPUVA
386 (
387 OBJGPU *pGpu,
388 Device *pDevice,
389 NvHandle hMemoryCtx,
390 NvU64 NotifyGPUVABase,
391 NvV32 Info32,
392 NvV16 Info16,
393 NV_STATUS CompletionStatus,
394 NvU32 Index
395 )
396 {
397 OBJTMR *pTmr = GPU_GET_TIMER(pGpu);
398 NvU64 Time;
399
400 tmrGetCurrentTime(pTmr, &Time);
401
402 return notifyFillNotifierGPUVATimestamp(pGpu,
403 pDevice,
404 hMemoryCtx,
405 NotifyGPUVABase,
406 Info32,
407 Info16,
408 CompletionStatus,
409 Index,
410 Time);
411 }
412
413 /*
414 * @brief fills notifiers by given memory info and index with given time, info,
415 * and completion status
416 *
417 * Use this function to fill notifier through BAR2 when you have memory info.
418 *
419
420 * @param[in] pGpu OBJGPU pointer
421 * @param[in] hClient NvU32 client handle
422 * @param[in] NotifyGPUVABase 64b GPU VA base address of semaphore
423 * @param[in] Info32 32b info part
424 * @param[in] Info16 16b info part
425 * @param[in] CompletionStatus NV_STATUS value to write to notifier status
426 * @param[in] Index index of notifier in notifier array
427 *
428 * @return NV_ERR_GENERIC if RM aperture mapping failed.
429 */
notifyFillNotifierMemoryTimestamp(OBJGPU * pGpu,Memory * pMemory,NvV32 Info32,NvV16 Info16,NV_STATUS CompletionStatus,NvU32 Index,NvU64 Time)430 NV_STATUS notifyFillNotifierMemoryTimestamp
431 (
432 OBJGPU *pGpu,
433 Memory *pMemory,
434 NvV32 Info32,
435 NvV16 Info16,
436 NV_STATUS CompletionStatus,
437 NvU32 Index,
438 NvU64 Time
439 )
440 {
441 NvNotification * pDebugNotifier = NULL;
442 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu);
443 KernelBus *pKernelBus = GPU_GET_KERNEL_BUS(pGpu);
444 TRANSFER_SURFACE surf = {0};
445
446 //
447 // Check if there's already a CPU mapping we can use. If not, attempt to
448 // map the notifier, which may fail if we're in a context where we can't
449 // create mappings.
450 //
451 pDebugNotifier = (NvNotification *)((NvUPtr)pMemory->KernelVAddr);
452 if (pDebugNotifier == NULL)
453 {
454 surf.pMemDesc = pMemory->pMemDesc;
455 surf.offset = Index * sizeof(NvNotification);
456
457 pDebugNotifier =
458 (NvNotification *) memmgrMemBeginTransfer(pMemoryManager, &surf,
459 sizeof(NvNotification),
460 TRANSFER_FLAGS_SHADOW_ALLOC);
461 NV_ASSERT_OR_RETURN(pDebugNotifier != NULL, NV_ERR_INVALID_STATE);
462 }
463 else
464 {
465 //
466 // If a CPU pointer has been passed by caller ensure that the notifier
467 // is in sysmem or in case it in vidmem, BAR access to the same is not
468 // blocked (for HCC)
469 //
470 NV_ASSERT_OR_RETURN(
471 memdescGetAddressSpace(pMemory->pMemDesc) == ADDR_SYSMEM ||
472 !kbusIsBarAccessBlocked(pKernelBus), NV_ERR_INVALID_ARGUMENT);
473 pDebugNotifier = &pDebugNotifier[Index];
474 }
475
476 notifyFillNvNotification(pGpu, pDebugNotifier, Info32, Info16,
477 CompletionStatus, NV_TRUE, Time);
478
479 if (pMemory->KernelVAddr == NvP64_NULL)
480 {
481 memmgrMemEndTransfer(pMemoryManager, &surf, sizeof(NvNotification), 0);
482 }
483
484 return NV_OK;
485 }
486
487 /*
488 * @brief fills notifiers by given memory info and index with current time,
489 * info and completion status.
490 *
491 * Use this function to fill notifier through BAR2 when you have memory info.
492 *
493 * Current time wrapper around notifyFillNotifierMemoryTimestamp.
494 *
495 * @param[in] pGpu OBJGPU pointer
496 * @param[in] hClient NvU32 client handle
497 * @param[in] NotifyGPUVABase 64b GPU VA base address of semaphore
498 * @param[in] Info32 32b info part
499 * @param[in] Info16 16b info part
500 * @param[in] CompletionStatus NV_STATUS value to write to notifier status
501 * @param[in] Index index of notifier in notifier array
502 *
503 * @return status of notifyFillNotifierMemoryTimestamp
504 */
notifyFillNotifierMemory(OBJGPU * pGpu,Memory * pMemory,NvV32 Info32,NvV16 Info16,NV_STATUS CompletionStatus,NvU32 Index)505 NV_STATUS notifyFillNotifierMemory
506 (
507 OBJGPU *pGpu,
508 Memory *pMemory,
509 NvV32 Info32,
510 NvV16 Info16,
511 NV_STATUS CompletionStatus,
512 NvU32 Index
513 )
514 {
515 OBJTMR *pTmr = GPU_GET_TIMER(pGpu);
516 NvU64 Time;
517
518 tmrGetCurrentTime(pTmr, &Time);
519
520 return notifyFillNotifierMemoryTimestamp(pGpu,
521 pMemory,
522 Info32,
523 Info16,
524 CompletionStatus,
525 Index,
526 Time);
527
528 }
529
530 /*
531 * @brief fill semaphore structure at GPU VA base given time and release value
532 *
533 * Looks up dma memory mapping with given GPU VA and performs writes.
534 * Semaphore write is skipped when CPU kernel mapping is missing.
535 *
536 * @param[in] pGpu OBJGPU pointer
537 * @param[in] pDevice Device pointer
538 * @param[in] SemaphoreGPUVABase 64b GPU VA base address of semaphore
539 * @param[in] ReleaseValue NvU32 value to write to semaphore upon release
540 * @param[in] Index index of semaphore in semaphore array
541 * @param[in] Time 64b time stamp
542 *
543 * @return NV_ERR_INVALID_ADDRESS on wrong GPU VA address or out of bound index,
544 * NV_OK on success
545 *
546 */
semaphoreFillGPUVATimestamp(OBJGPU * pGpu,Device * pDevice,NvHandle hMemCtx,NvU64 SemaphoreGPUVABase,NvV32 ReleaseValue,NvU32 Index,NvBool bBroadcast,NvU64 Time)547 NV_STATUS semaphoreFillGPUVATimestamp
548 (
549 OBJGPU *pGpu,
550 Device *pDevice,
551 NvHandle hMemCtx,
552 NvU64 SemaphoreGPUVABase,
553 NvV32 ReleaseValue,
554 NvU32 Index,
555 NvBool bBroadcast,
556 NvU64 Time
557 )
558 {
559 NvU64 semaphoreGPUVA;
560 NvU64 semaphoreGPUVAOffset;
561 CLI_DMA_MAPPING_INFO *pDmaMappingInfo;
562 NvU64 offset;
563 NvU32 timeHi, timeLo;
564 NvU32 subdeviceInstance;
565 NvGpuSemaphore *pSemaphore;
566 NvBool bBcState = gpumgrGetBcEnabledStatus(pGpu);
567 NvBool bFound;
568
569 if (!portSafeMulU64((NvU64) Index,
570 (NvU64) sizeof(NvGpuSemaphore),
571 &semaphoreGPUVAOffset) ||
572 !portSafeAddU64(SemaphoreGPUVABase,
573 semaphoreGPUVAOffset,
574 &semaphoreGPUVA))
575 {
576 return NV_ERR_INVALID_ARGUMENT;
577 }
578
579 bFound = CliGetDmaMappingInfo(RES_GET_CLIENT(pDevice),
580 RES_GET_HANDLE(pDevice),
581 hMemCtx,
582 semaphoreGPUVA,
583 gpumgrGetDeviceGpuMask(pGpu->deviceInstance),
584 &pDmaMappingInfo);
585 if (!bFound)
586 {
587 NV_PRINTF(LEVEL_ERROR, "Can't find mapping; semaphore not released\n");
588 return NV_ERR_INVALID_ADDRESS;
589 }
590
591 offset = semaphoreGPUVA - pDmaMappingInfo->DmaOffset;
592 if ((offset + sizeof(NvGpuSemaphore)) > pDmaMappingInfo->pMemDesc->Size)
593 {
594 NV_PRINTF(LEVEL_ERROR,
595 "offset+size doesn't fit into mapping; semaphore not released\n");
596 return NV_ERR_INVALID_ADDRESS;
597 }
598
599 timeLo = NvU64_LO32(Time);
600 timeHi = NvU64_HI32(Time);
601
602 //
603 // Set idx to default position in the dma mapped address array
604 //
605 subdeviceInstance = gpumgrGetSubDeviceInstanceFromGpu(gpumgrGetParentGPU(pGpu));
606
607 osFlushCpuWriteCombineBuffer();
608
609 gpumgrSetBcEnabledStatus(pGpu, bBroadcast);
610 SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY)
611
612 if (IsSLIEnabled(pGpu) &&
613 (memdescGetAddressSpace(pDmaMappingInfo->pMemDesc) == ADDR_FBMEM))
614 {
615 //
616 // If SLI and it is vidmem, replace idx with appropriate SLI index
617 // otherwise, this just stays the default value.
618 //
619 subdeviceInstance = gpumgrGetSubDeviceInstanceFromGpu(pGpu);
620 }
621
622 if (!pDmaMappingInfo->KernelVAddr[subdeviceInstance])
623 {
624 NV_PRINTF(LEVEL_ERROR, "KernelVAddr==NULL; semaphore not released\n");
625 }
626 else
627 {
628 pSemaphore = (NvGpuSemaphore*)((NvU8*)pDmaMappingInfo->KernelVAddr[subdeviceInstance] + offset);
629
630 MEM_WR32(&(pSemaphore->timeStamp.nanoseconds[0]), timeLo);
631 MEM_WR32(&(pSemaphore->timeStamp.nanoseconds[1]), timeHi);
632 MEM_WR32(&(pSemaphore->data[0]), ReleaseValue);
633 }
634
635 SLI_LOOP_END
636
637 gpumgrSetBcEnabledStatus(pGpu, bBcState);
638 osFlushCpuWriteCombineBuffer();
639
640 return NV_OK;
641 }
642
643 /*
644 * @brief fill semaphore at GPU VA with given release value and current time stamp
645 *
646 * Use this function to fill Semaphore through BAR1 when you have GPU VA.
647 *
648 * Wrapper for semaphore handling. Gets current time and routes data to
649 * semaphoreFillGPUVATimestamp.
650 *
651 * @param[in] pGpu OBJGPU pointer
652 * @param[in] pDevice Device pointer
653 * @param[in] SemaphoreGPUVABase 64b GPU VA base address of semaphore
654 * @param[in] ReleaseValue NvU32 value to write to semaphore upon release
655 * @param[in] Index index of semaphore in semaphore array
656 *
657 * @return status of semaphoreFillGPUVATimestamp
658 */
semaphoreFillGPUVA(OBJGPU * pGpu,Device * pDevice,NvHandle hMemCtx,NvU64 SemaphoreGPUVABase,NvV32 ReleaseValue,NvU32 Index,NvBool bBroadcast)659 NV_STATUS semaphoreFillGPUVA
660 (
661 OBJGPU *pGpu,
662 Device *pDevice,
663 NvHandle hMemCtx,
664 NvU64 SemaphoreGPUVABase,
665 NvV32 ReleaseValue,
666 NvU32 Index,
667 NvBool bBroadcast
668 )
669 {
670 OBJTMR *pTmr = GPU_GET_TIMER(pGpu);
671 NvU64 Time;
672
673 tmrGetCurrentTime(pTmr, &Time);
674
675 return semaphoreFillGPUVATimestamp(pGpu,
676 pDevice,
677 hMemCtx,
678 SemaphoreGPUVABase,
679 ReleaseValue,
680 Index,
681 bBroadcast,
682 Time);
683 }
684