1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2019-2022 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 "bios_nvswitch.h"
25 #include "error_nvswitch.h"
26 #include "rmsoecmdif.h"
27 #include "nvswitch/lr10/dev_ext_devices.h"
28
29 #include "flcn/flcn_nvswitch.h"
30
31 #include "rmflcncmdif_nvswitch.h"
32 #include "haldef_nvswitch.h"
33
34 static NvlStatus
_nvswitch_core_bios_read(nvswitch_device * device,NvU8 readType,NvU32 reqSize,NvU8 * pData)35 _nvswitch_core_bios_read
36 (
37 nvswitch_device *device,
38 NvU8 readType,
39 NvU32 reqSize,
40 NvU8 *pData
41 )
42 {
43 #define MAX_READ_SIZE 0x2000
44 RM_FLCN_CMD_SOE cmd;
45 NVSWITCH_TIMEOUT timeout;
46 NvU32 cmdSeqDesc = 0;
47 NV_STATUS status;
48 FLCN *pFlcn = NULL;
49 RM_SOE_CORE_CMD_BIOS *pParams = &cmd.cmd.core.bios;
50 NvU64 dmaHandle = 0;
51 NvU8 *pReadBuffer = NULL;
52 NvU32 offset = 0;
53 NvU32 bufferSize = (reqSize < SOE_DMA_MAX_SIZE) ? SOE_DMA_MAX_SIZE : MAX_READ_SIZE;
54
55 // Create DMA mapping for SOE CORE transactions
56 status = nvswitch_os_alloc_contig_memory(device->os_handle,
57 (void**)&pReadBuffer, bufferSize, (device->dma_addr_width == 32));
58 if (status != NVL_SUCCESS)
59 {
60 NVSWITCH_PRINT(device, ERROR, "Failed to allocate contig memory\n");
61 return status;
62 }
63
64 status = nvswitch_os_map_dma_region(device->os_handle,
65 pReadBuffer,
66 &dmaHandle,
67 bufferSize,
68 NVSWITCH_DMA_DIR_TO_SYSMEM);
69 if (status != NVL_SUCCESS)
70 {
71 NVSWITCH_PRINT(device, ERROR, "Failed to map dma region to sysmem\n");
72 nvswitch_os_free_contig_memory(device->os_handle, pReadBuffer, bufferSize);
73 return status;
74 }
75
76 pFlcn = device->pSoe->pFlcn;
77
78 while (offset < reqSize)
79 {
80 nvswitch_os_memset(pReadBuffer, 0, bufferSize);
81 nvswitch_os_memset(&cmd, 0, sizeof(cmd));
82
83 cmd.hdr.unitId = RM_SOE_UNIT_CORE;
84 cmd.hdr.size = RM_SOE_CMD_SIZE(CORE, BIOS);
85 cmd.cmd.core.bios.cmdType = readType;
86 RM_FLCN_U64_PACK(&pParams->dmaHandle, &dmaHandle);
87 pParams->offset = offset;
88 pParams->sizeInBytes = NV_MIN((reqSize - offset), MAX_READ_SIZE);
89 cmdSeqDesc = 0;
90
91 status = nvswitch_os_sync_dma_region_for_device(device->os_handle, dmaHandle,
92 bufferSize, NVSWITCH_DMA_DIR_TO_SYSMEM);
93 if (status != NV_OK)
94 {
95 nvswitch_os_unmap_dma_region(device->os_handle, pReadBuffer, dmaHandle,
96 bufferSize, NVSWITCH_DMA_DIR_TO_SYSMEM);
97 nvswitch_os_free_contig_memory(device->os_handle, pReadBuffer, bufferSize);
98 NVSWITCH_PRINT(device, ERROR, "Failed to yield to DMA controller\n");
99 return status;
100 }
101
102 nvswitch_timeout_create(NVSWITCH_INTERVAL_1SEC_IN_NS * 4, &timeout);
103
104 status = flcnQueueCmdPostBlocking(device, pFlcn,
105 (PRM_FLCN_CMD)&cmd,
106 NULL, // pMsg - not used for now
107 NULL, // pPayload - not used for now
108 SOE_RM_CMDQ_LOG_ID,
109 &cmdSeqDesc,
110 &timeout);
111 if (status != NV_OK)
112 {
113 NVSWITCH_PRINT(device, ERROR, "%s: CORE read failed. rc:%d\n",
114 __FUNCTION__, status);
115 break;
116 }
117
118 status = nvswitch_os_sync_dma_region_for_cpu(device->os_handle, dmaHandle,
119 bufferSize, NVSWITCH_DMA_DIR_TO_SYSMEM);
120 if (status != NV_OK)
121 {
122 NVSWITCH_PRINT(device, ERROR, "DMA controller failed to yield back\n");
123 break;
124 }
125
126 if (readType == RM_SOE_CORE_CMD_READ_BIOS)
127 {
128 nvswitch_os_memcpy(((NvU8*)&pData[offset]), pReadBuffer, pParams->sizeInBytes);
129 }
130 else if (readType == RM_SOE_CORE_CMD_READ_BIOS_SIZE)
131 {
132 nvswitch_os_memcpy(((NvU8*)pData), pReadBuffer, reqSize);
133 break;
134 }
135
136 offset += pParams->sizeInBytes;
137 }
138
139 nvswitch_os_unmap_dma_region(device->os_handle, pReadBuffer, dmaHandle,
140 bufferSize, NVSWITCH_DMA_DIR_TO_SYSMEM);
141
142 nvswitch_os_free_contig_memory(device->os_handle, pReadBuffer, bufferSize);
143 return status;
144 }
145
146 NvlStatus
nvswitch_bios_read(nvswitch_device * device,NvU32 size,void * pData)147 nvswitch_bios_read
148 (
149 nvswitch_device *device,
150 NvU32 size,
151 void *pData
152 )
153 {
154 return _nvswitch_core_bios_read(device, RM_SOE_CORE_CMD_READ_BIOS, size, (NvU8*)pData);
155 }
156
157 NvlStatus
nvswitch_bios_read_size(nvswitch_device * device,NvU32 * pSize)158 nvswitch_bios_read_size
159 (
160 nvswitch_device *device,
161 NvU32 *pSize
162 )
163 {
164 if (pSize == NULL)
165 {
166 return -NVL_BAD_ARGS;
167 }
168
169 return _nvswitch_core_bios_read(device, RM_SOE_CORE_CMD_READ_BIOS_SIZE, sizeof(NvU32), (NvU8*)pSize);
170 }
171
172 /*!
173 * @brief Retrieves BIOS Image via SOE's CORE task
174 * This function needs SOE to be initialized for the Util task to respond.
175 * Upon success the BIOS Image will be place in device.biosImage
176 * @param[in/out] device - pointer to the nvswitch device.
177 */
178 NvlStatus
nvswitch_bios_get_image(nvswitch_device * device)179 nvswitch_bios_get_image
180 (
181 nvswitch_device *device
182 )
183 {
184 NvU8 *pBiosRawBuffer = NULL;
185 NvlStatus status = NVL_SUCCESS;
186 NvU32 biosSize = 0;
187
188 if (device->biosImage.pImage != NULL)
189 {
190 NVSWITCH_PRINT(device, ERROR,
191 "NVRM: %s: bios already available, skip reading"
192 "\n", __FUNCTION__);
193
194 return NVL_SUCCESS;
195 }
196
197 if (!device->pSoe)
198 {
199 NVSWITCH_PRINT(device, ERROR,
200 "%s: SOE not initialized yet. \n",
201 __FUNCTION__);
202 return NVL_SUCCESS;
203 }
204
205 status = device->hal.nvswitch_get_bios_size(device, &biosSize);
206 if (status != NVL_SUCCESS || biosSize == 0)
207 {
208 NVSWITCH_PRINT(device, ERROR,
209 "NVRM: %s: bios read size failed"
210 "\n", __FUNCTION__);
211 return status;
212 }
213
214 NVSWITCH_PRINT(device, SETUP,
215 "NVRM: %s: BIOS Size = 0x%x"
216 "\n", __FUNCTION__, biosSize);
217
218 pBiosRawBuffer = (NvU8*) nvswitch_os_malloc(biosSize);
219 if (pBiosRawBuffer == NULL)
220 {
221 NVSWITCH_PRINT(device, ERROR,
222 "%s : failed memory allocation"
223 "\n", __FUNCTION__);
224
225 return -NVL_NO_MEM;
226 }
227
228 nvswitch_os_memset(pBiosRawBuffer, 0, biosSize);
229
230 status = nvswitch_bios_read(device, biosSize, pBiosRawBuffer);
231 if (status != NVL_SUCCESS)
232 {
233 NVSWITCH_PRINT(device, ERROR, " Failed to retrieve BIOS image, Code 0x%x\n", status);
234 nvswitch_os_free(pBiosRawBuffer);
235 return status;
236 }
237
238 device->biosImage.pImage = pBiosRawBuffer;
239 device->biosImage.size = biosSize;
240
241 return NVL_SUCCESS;
242 }
243