1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 1993-2021 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 #include "core/core.h"
25 #include "os/os.h"
26 #include "gpu/gpu.h"
27 #include "gpu/subdevice/generic_engine.h"
28 #include "gpu/subdevice/subdevice.h"
29 #include "rmapi/client.h"
30 
31 #include <class/cl90e6.h>
32 #include <class/cl90e7.h>
33 
34 
35 NV_STATUS
36 genapiConstruct_IMPL
37 (
38     GenericEngineApi *pGenericEngineApi,
39     CALL_CONTEXT *pCallContext,
40     RS_RES_ALLOC_PARAMS_INTERNAL *pParams
41 )
42 {
43     RS_ITERATOR it;
44     OBJGPU     *pGpu = GPU_RES_GET_GPU(pGenericEngineApi);
45 
46     if (!gpuIsClassSupported(pGpu, pCallContext->pResourceRef->externalClassId))
47         return NV_ERR_INVALID_CLASS;
48 
49     //
50     // We allow multiple instances of GenericEngineApi class, however, only want
51     // to allow a single instance of each external class id type. E.g.:
52     // GF100_SUBDEVICE_GRAPHICS is allowed alongside GF100_SUBDEVICE_FB.
53     //
54     it = clientRefIter(pCallContext->pClient,
55                        pCallContext->pResourceRef->pParentRef,
56                        classId(GenericEngineApi), RS_ITERATE_CHILDREN, NV_TRUE);
57 
58     while (clientRefIterNext(pCallContext->pClient, &it))
59     {
60          if (it.pResourceRef->externalClassId == pCallContext->pResourceRef->externalClassId &&
61              it.pResourceRef != pCallContext->pResourceRef)
62          {
63              return NV_ERR_STATE_IN_USE;
64          }
65     }
66 
67     return NV_OK;
68 }
69 
70 void
71 genapiDestruct_IMPL
72 (
73     GenericEngineApi *pGenericEngineApi
74 )
75 {
76 }
77 
78 NV_STATUS
79 genapiControl_IMPL
80 (
81     GenericEngineApi *pGenericEngineApi,
82     CALL_CONTEXT *pCallContext,
83     RS_RES_CONTROL_PARAMS_INTERNAL *pParams
84 )
85 {
86     if (RES_GET_EXT_CLASS_ID(pGenericEngineApi) == GF100_SUBDEVICE_INFOROM)
87     {
88         OBJGPU     *pGpu     = GPU_RES_GET_GPU(pGenericEngineApi);
89         OBJINFOROM *pInforom = GPU_GET_INFOROM(pGpu);
90         if (!IS_GSP_CLIENT(pGpu) && pInforom == NULL)
91         {
92             return NV_ERR_NOT_SUPPORTED;
93         }
94     }
95 
96     return gpuresControl_IMPL(staticCast(pGenericEngineApi, GpuResource),
97                               pCallContext, pParams);
98 }
99 
100 NV_STATUS
101 genapiMap_IMPL
102 (
103     GenericEngineApi *pGenericEngineApi,
104     CALL_CONTEXT *pCallContext,
105     RS_CPU_MAP_PARAMS *pParams,
106     RsCpuMapping *pCpuMapping
107 )
108 {
109     OBJGPU *pGpu;
110     NvU32 engineOffset, regSize, regBase;
111     NvU32 protect;
112     NV_STATUS rmStatus;
113 
114     pGpu = GPU_RES_GET_GPU(pGenericEngineApi);
115 
116     // XXX The default should really be more restrictive
117     protect = NV_PROTECT_READ_WRITE;
118 
119     switch (RES_GET_EXT_CLASS_ID(pGenericEngineApi))
120     {
121         case GF100_SUBDEVICE_MASTER:
122         {
123             regSize = sizeof(GF100MASTERMap);
124             regBase = NV_REG_BASE_MASTER;
125             protect = NV_PROTECT_READABLE;
126             break;
127         }
128         default:
129             return NV_ERR_INVALID_CLASS;
130     }
131 
132     // Get the offset to the engine registers
133     rmStatus = gpuGetRegBaseOffset_HAL(pGpu, regBase, &engineOffset);
134     if (rmStatus != NV_OK)
135         return rmStatus;
136 
137     // Round down to nearest 4k page
138     engineOffset &= ~(0x1000-1);
139 
140     // Check the caller is requesting more privilieges than we allow
141     if (pCpuMapping->pPrivate->protect & ~protect)
142     {
143         NV_PRINTF(LEVEL_ERROR, "%s%saccess not allowed on class 0x%x\n",
144                   (pCpuMapping->pPrivate->protect & ~protect) & NV_PROTECT_READABLE ? "Read " : "",
145                   (pCpuMapping->pPrivate->protect & ~protect) & NV_PROTECT_WRITEABLE ? "Write " : "",
146                   RES_GET_EXT_CLASS_ID(pGenericEngineApi));
147 
148         return NV_ERR_PROTECTION_FAULT;
149     }
150 
151     // Create mapping
152     rmStatus = rmapiMapGpuCommon(staticCast(pGenericEngineApi, RsResource),
153                                  pCallContext,
154                                  pCpuMapping,
155                                  pGpu,
156                                  engineOffset,
157                                  regSize);
158     pCpuMapping->processId = osGetCurrentProcess();
159 
160     if (pParams->ppCpuVirtAddr)
161         *pParams->ppCpuVirtAddr = pCpuMapping->pLinearAddress;
162 
163     return rmStatus;
164 }
165 
166 NV_STATUS
167 genapiGetMapAddrSpace_IMPL
168 (
169     GenericEngineApi *pGenericEngineApi,
170     CALL_CONTEXT *pCallContext,
171     NvU32 mapFlags,
172     NV_ADDRESS_SPACE *pAddrSpace
173 )
174 {
175     if (pAddrSpace)
176         *pAddrSpace = ADDR_REGMEM;
177 
178     return NV_OK;
179 }
180 
181