1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2017-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 #include "common_nvswitch.h"
25 #include "rom_nvswitch.h"
26 #include "error_nvswitch.h"
27 #include "regkey_nvswitch.h"
28 #include "bios_nvswitch.h"
29 #include "haldef_nvswitch.h"
30 #include "flcn/haldefs_flcnable_nvswitch.h"
31 #include "flcn/flcn_nvswitch.h"
32 #include "soe/soe_nvswitch.h"
33 #include "soe/soeififr.h"
34 #include "nvVer.h"
35 #include "nvlink_inband_msg.h"
36 #include "cci/cci_nvswitch.h"
37 
38 static NvlStatus _nvswitch_ctrl_inband_flush_data(nvswitch_device *device, NVSWITCH_INBAND_FLUSH_DATA_PARAMS *p);
39 
40 #define NVSWITCH_DEV_CMD_CHECK_ADMIN    NVBIT64(0)
41 #define NVSWITCH_DEV_CMD_CHECK_FM       NVBIT64(1)
42 
43 #define NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(cmd, function, type, private, flags)\
44     case cmd:                                                                    \
45     {                                                                            \
46         if (sizeof(type) != size)                                                \
47         {                                                                        \
48             retval = -NVL_BAD_ARGS;                                              \
49             break;                                                               \
50         }                                                                        \
51                                                                                  \
52         retval = _nvswitch_lib_validate_privileged_ctrl(private, flags);         \
53         if (retval != NVL_SUCCESS)                                               \
54         {                                                                        \
55             break;                                                               \
56         }                                                                        \
57                                                                                  \
58         retval = function(device, params);                                       \
59         break;                                                                   \
60     }                                                                            \
61 
62 #define NVSWITCH_DEV_CMD_DISPATCH_RESERVED(cmd)                                  \
63     case cmd:                                                                    \
64     {                                                                            \
65         retval = -NVL_ERR_NOT_SUPPORTED;                                         \
66         break;                                                                   \
67     }                                                                            \
68 
69 const static NvU32 nvswitch_lr10_device_ids[] =
70 {
71     0x1AE8, 0x1AF0, 0x1AF1, 0x1AF2, 0x1AF3, 0x1AF4, 0x1AF5, 0x1AF6, 0x1AF7,
72     0x1AF8, 0x1AF9, 0x1AFA, 0x1AFB, 0x1AFC, 0x1AFD, 0x1AFE, 0x1AFF
73 };
74 
75 const static NvU32 nvswitch_ls10_device_ids[] =
76 {
77     // PCIE endpoint to manage the NVLink switch HW
78     0x22A0, 0x22A1, 0x22A2, 0x22A3, 0x22A4, 0x22A5, 0x22A6, 0x22A7,
79     // PCI-PCI Bridge, Laguna Switch Function 0
80     0x22A8, 0x22A9, 0x22AA, 0x22AB,
81     // Non-Transparent Bridge, Laguna Switch Function 1
82     0x22AC, 0x22AD, 0x22AE, 0x22AF
83 };
84 
85 nvlink_link_handlers link_handlers;
86 
87 static NvBool
_nvswitch_is_device_id_present(const NvU32 * array,NvU32 array_len,NvU32 device_id)88 _nvswitch_is_device_id_present
89 (
90     const NvU32 *array,
91     NvU32 array_len,
92     NvU32 device_id
93 )
94 {
95     NvU32 i = 0;
96 
97     for(i = 0; i < array_len; i++)
98     {
99         if (array[i] == device_id)
100         {
101             return NV_TRUE;
102         }
103     }
104 
105     return NV_FALSE;
106 }
107 
108 NvBool
nvswitch_is_lr10_device_id(NvU32 device_id)109 nvswitch_is_lr10_device_id
110 (
111     NvU32 device_id
112 )
113 {
114     NvU32 count = (sizeof(nvswitch_lr10_device_ids) /
115                         sizeof(nvswitch_lr10_device_ids[0]));
116 
117     return _nvswitch_is_device_id_present(nvswitch_lr10_device_ids, count, device_id);
118 }
119 
120 NvBool
nvswitch_is_ls10_device_id(NvU32 device_id)121 nvswitch_is_ls10_device_id
122 (
123     NvU32 device_id
124 )
125 {
126     NvU32 count = (sizeof(nvswitch_ls10_device_ids) /
127                         sizeof(nvswitch_ls10_device_ids[0]));
128 
129     return _nvswitch_is_device_id_present(nvswitch_ls10_device_ids, count, device_id);
130 }
131 
132 /*
133  * NVLink corelib callbacks are used by the NVLink library separate from the
134  * NVSwitch driver, therefore they do not take a device lock and can not modify
135  * nvswitch_device state or use error logging.
136  *
137  * These NVSwitch functions modify link state outside of the corelib:
138  *   _nvswitch_ctrl_inject_link_error - injects asynchronous link errors (MODS-only)
139  */
140 
141 static NV_API_CALL NvlStatus
_nvswitch_corelib_add_link(nvlink_link * link)142 _nvswitch_corelib_add_link
143 (
144     nvlink_link *link
145 )
146 {
147     nvswitch_device *device = link->dev->pDevInfo;
148     return device->hal.nvswitch_corelib_add_link(link);
149 }
150 
151 static NV_API_CALL NvlStatus
_nvswitch_corelib_remove_link(nvlink_link * link)152 _nvswitch_corelib_remove_link
153 (
154     nvlink_link *link
155 )
156 {
157     nvswitch_device *device = link->dev->pDevInfo;
158     return device->hal.nvswitch_corelib_remove_link(link);
159 }
160 
161 static NV_API_CALL NvlStatus
_nvswitch_corelib_set_dl_link_mode(nvlink_link * link,NvU64 mode,NvU32 flags)162 _nvswitch_corelib_set_dl_link_mode
163 (
164     nvlink_link *link,
165     NvU64 mode,
166     NvU32 flags
167 )
168 {
169     nvswitch_device *device = link->dev->pDevInfo;
170     return device->hal.nvswitch_corelib_set_dl_link_mode(link, mode, flags);
171 }
172 
173 static NV_API_CALL NvlStatus
_nvswitch_corelib_get_dl_link_mode(nvlink_link * link,NvU64 * mode)174 _nvswitch_corelib_get_dl_link_mode
175 (
176     nvlink_link *link,
177     NvU64 *mode
178 )
179 {
180     nvswitch_device *device = link->dev->pDevInfo;
181     return device->hal.nvswitch_corelib_get_dl_link_mode(link, mode);
182 }
183 
184 static NV_API_CALL NvlStatus
_nvswitch_corelib_set_tl_link_mode(nvlink_link * link,NvU64 mode,NvU32 flags)185 _nvswitch_corelib_set_tl_link_mode
186 (
187     nvlink_link *link,
188     NvU64 mode,
189     NvU32 flags
190 )
191 {
192     nvswitch_device *device = link->dev->pDevInfo;
193     return device->hal.nvswitch_corelib_set_tl_link_mode(link, mode, flags);
194 }
195 
196 static NV_API_CALL NvlStatus
_nvswitch_corelib_get_tl_link_mode(nvlink_link * link,NvU64 * mode)197 _nvswitch_corelib_get_tl_link_mode
198 (
199     nvlink_link *link,
200     NvU64 *mode
201 )
202 {
203     nvswitch_device *device = link->dev->pDevInfo;
204     return device->hal.nvswitch_corelib_get_tl_link_mode(link, mode);
205 }
206 
207 static NV_API_CALL NvlStatus
_nvswitch_corelib_set_tx_mode(nvlink_link * link,NvU64 mode,NvU32 flags)208 _nvswitch_corelib_set_tx_mode
209 (
210     nvlink_link *link,
211     NvU64 mode,
212     NvU32 flags
213 )
214 {
215     nvswitch_device *device = link->dev->pDevInfo;
216     return device->hal.nvswitch_corelib_set_tx_mode(link, mode, flags);
217 }
218 
219 static NV_API_CALL NvlStatus
_nvswitch_corelib_get_tx_mode(nvlink_link * link,NvU64 * mode,NvU32 * subMode)220 _nvswitch_corelib_get_tx_mode
221 (
222     nvlink_link *link,
223     NvU64 *mode,
224     NvU32 *subMode
225 )
226 {
227     nvswitch_device *device = link->dev->pDevInfo;
228     return device->hal.nvswitch_corelib_get_tx_mode(link, mode, subMode);
229 }
230 
231 static NV_API_CALL NvlStatus
_nvswitch_corelib_set_rx_mode(nvlink_link * link,NvU64 mode,NvU32 flags)232 _nvswitch_corelib_set_rx_mode
233 (
234     nvlink_link *link,
235     NvU64 mode,
236     NvU32 flags
237 )
238 {
239     nvswitch_device *device = link->dev->pDevInfo;
240     return device->hal.nvswitch_corelib_set_rx_mode(link, mode, flags);
241 }
242 
243 static NV_API_CALL NvlStatus
_nvswitch_corelib_get_rx_mode(nvlink_link * link,NvU64 * mode,NvU32 * subMode)244 _nvswitch_corelib_get_rx_mode
245 (
246     nvlink_link *link,
247     NvU64 *mode,
248     NvU32 *subMode
249 )
250 {
251     nvswitch_device *device = link->dev->pDevInfo;
252     return device->hal.nvswitch_corelib_get_rx_mode(link, mode, subMode);
253 }
254 
255 static NV_API_CALL NvlStatus
_nvswitch_corelib_set_rx_detect(nvlink_link * link,NvU32 flags)256 _nvswitch_corelib_set_rx_detect
257 (
258     nvlink_link *link,
259     NvU32 flags
260 )
261 {
262     nvswitch_device *device = link->dev->pDevInfo;
263     return device->hal.nvswitch_corelib_set_rx_detect(link, flags);
264 }
265 
266 static NV_API_CALL NvlStatus
_nvswitch_corelib_get_rx_detect(nvlink_link * link)267 _nvswitch_corelib_get_rx_detect
268 (
269     nvlink_link *link
270 )
271 {
272     nvswitch_device *device = link->dev->pDevInfo;
273     return device->hal.nvswitch_corelib_get_rx_detect(link);
274 }
275 
276 static NV_API_CALL void
_nvswitch_corelib_training_complete(nvlink_link * link)277 _nvswitch_corelib_training_complete
278 (
279     nvlink_link *link
280 )
281 {
282     nvswitch_device *device = link->dev->pDevInfo;
283     device->hal.nvswitch_corelib_training_complete(link);
284 }
285 
286 static NV_API_CALL void
_nvswitch_corelib_get_uphy_load(nvlink_link * link,NvBool * bUnlocked)287 _nvswitch_corelib_get_uphy_load
288 (
289     nvlink_link *link,
290     NvBool *bUnlocked
291 )
292 {
293     nvswitch_device *device = link->dev->pDevInfo;
294     return device->hal.nvswitch_corelib_get_uphy_load(link, bUnlocked);
295 }
296 
297 
298 static NV_API_CALL NvlStatus
_nvswitch_corelib_write_discovery_token(nvlink_link * link,NvU64 token)299 _nvswitch_corelib_write_discovery_token
300 (
301     nvlink_link *link,
302     NvU64 token
303 )
304 {
305     nvswitch_device *device = link->dev->pDevInfo;
306 
307     if (link->version >= NVLINK_DEVICE_VERSION_40)
308     {
309         nvswitch_store_topology_information(device, link);
310         return NVL_SUCCESS;
311     }
312 
313     return NVL_SUCCESS;
314 }
315 
316 static NV_API_CALL NvlStatus
_nvswitch_corelib_read_discovery_token(nvlink_link * link,NvU64 * token)317 _nvswitch_corelib_read_discovery_token
318 (
319     nvlink_link *link,
320     NvU64 *token
321 )
322 {
323     if (link->version >= NVLINK_DEVICE_VERSION_40)
324     {
325         return NVL_SUCCESS;
326     }
327     return NVL_SUCCESS;
328 }
329 
330 static NV_API_CALL NvlStatus
_nvswitch_corelib_get_cci_link_mode(nvlink_link * link,NvU64 * mode)331 _nvswitch_corelib_get_cci_link_mode
332 (
333     nvlink_link *link,
334     NvU64 *mode
335 )
336 {
337     nvswitch_device *device = link->dev->pDevInfo;
338     return device->hal.nvswitch_cci_get_cci_link_mode(device, link->linkNumber, mode);
339 }
340 
341 static NV_API_CALL NvlStatus
_nvswitch_corelib_ali_training(nvlink_link * link)342 _nvswitch_corelib_ali_training
343 (
344     nvlink_link *link
345 )
346 {
347     nvswitch_device *device = link->dev->pDevInfo;
348     return device->hal.nvswitch_launch_ALI_link_training(device, link, NV_FALSE);
349 }
350 
351 void
nvswitch_get_link_handlers(nvlink_link_handlers * nvswitch_link_handlers)352 nvswitch_get_link_handlers
353 (
354     nvlink_link_handlers *nvswitch_link_handlers
355 )
356 {
357     if (!nvswitch_link_handlers)
358     {
359         NVSWITCH_ASSERT(0);
360         return;
361     }
362 
363     nvswitch_link_handlers->add = _nvswitch_corelib_add_link;
364     nvswitch_link_handlers->remove = _nvswitch_corelib_remove_link;
365     nvswitch_link_handlers->set_dl_link_mode = _nvswitch_corelib_set_dl_link_mode;
366     nvswitch_link_handlers->get_dl_link_mode = _nvswitch_corelib_get_dl_link_mode;
367     nvswitch_link_handlers->set_tl_link_mode = _nvswitch_corelib_set_tl_link_mode;
368     nvswitch_link_handlers->get_tl_link_mode = _nvswitch_corelib_get_tl_link_mode;
369     nvswitch_link_handlers->set_tx_mode = _nvswitch_corelib_set_tx_mode;
370     nvswitch_link_handlers->get_tx_mode = _nvswitch_corelib_get_tx_mode;
371     nvswitch_link_handlers->set_rx_mode = _nvswitch_corelib_set_rx_mode;
372     nvswitch_link_handlers->get_rx_mode = _nvswitch_corelib_get_rx_mode;
373     nvswitch_link_handlers->set_rx_detect = _nvswitch_corelib_set_rx_detect;
374     nvswitch_link_handlers->get_rx_detect = _nvswitch_corelib_get_rx_detect;
375     nvswitch_link_handlers->training_complete = _nvswitch_corelib_training_complete;
376     nvswitch_link_handlers->get_uphy_load = _nvswitch_corelib_get_uphy_load;
377     nvswitch_link_handlers->write_discovery_token = _nvswitch_corelib_write_discovery_token;
378     nvswitch_link_handlers->read_discovery_token = _nvswitch_corelib_read_discovery_token;
379     nvswitch_link_handlers->ali_training = _nvswitch_corelib_ali_training;
380     nvswitch_link_handlers->get_cci_link_mode = _nvswitch_corelib_get_cci_link_mode;
381 }
382 
383 #define NVSWITCH_INIT_REGKEY(_private, _regkey, _string, _default_val)          \
384 do                                                                              \
385 {                                                                               \
386     NvU32 data;                                                                 \
387                                                                                 \
388     device->regkeys._regkey = _default_val;                                     \
389     if (NV_SWITCH_REGKEY_PRIVATE_ALLOWED || !NV_SWITCH_REGKEY##_private)        \
390     {                                                                           \
391         if (NVL_SUCCESS ==                                                      \
392             nvswitch_os_read_registry_dword(device->os_handle, _string, &data)) \
393         {                                                                       \
394             NVSWITCH_PRINT(device, SETUP,                                       \
395                 "%s: Applying regkey %s=0x%x\n",                                \
396                 __FUNCTION__,                                                   \
397                 _string, data);                                                 \
398             device->regkeys._regkey = data;                                     \
399         }                                                                       \
400     }                                                                           \
401 } while(0)
402 
403 static void
_nvswitch_init_device_regkeys(nvswitch_device * device)404 _nvswitch_init_device_regkeys
405 (
406     nvswitch_device *device
407 )
408 {
409     //
410     // Public external use regkeys
411     //
412     NVSWITCH_INIT_REGKEY(_PUBLIC, ato_control,
413                          NV_SWITCH_REGKEY_ATO_CONTROL,
414                          NV_SWITCH_REGKEY_ATO_CONTROL_DEFAULT);
415 
416     NVSWITCH_INIT_REGKEY(_PUBLIC, sto_control,
417                          NV_SWITCH_REGKEY_STO_CONTROL,
418                          NV_SWITCH_REGKEY_STO_CONTROL_DEFAULT);
419 
420     NVSWITCH_INIT_REGKEY(_PUBLIC, crc_bit_error_rate_short,
421                          NV_SWITCH_REGKEY_CRC_BIT_ERROR_RATE_SHORT,
422                          NV_SWITCH_REGKEY_CRC_BIT_ERROR_RATE_SHORT_DEFAULT);
423 
424     NVSWITCH_INIT_REGKEY(_PUBLIC, crc_bit_error_rate_long,
425                          NV_SWITCH_REGKEY_CRC_BIT_ERROR_RATE_LONG,
426                          NV_SWITCH_REGKEY_CRC_BIT_ERROR_RATE_LONG_DEFAULT);
427 
428     NVSWITCH_INIT_REGKEY(_PUBLIC, surpress_link_errors_for_gpu_reset,
429                          NV_SWITCH_REGKEY_SURPRESS_LINK_ERRORS_FOR_GPU_RESET,
430                          NV_SWITCH_REGKEY_SURPRESS_LINK_ERRORS_FOR_GPU_RESET_DISABLE);
431 
432     NVSWITCH_INIT_REGKEY(_PUBLIC, cci_control,
433                          NV_SWITCH_REGKEY_CCI_CONTROL,
434                          NV_SWITCH_REGKEY_CCI_CONTROL_DEFAULT);
435     NVSWITCH_INIT_REGKEY(_PRIVATE, cci_link_train_disable_mask,
436                          NV_SWITCH_REGKEY_CCI_DISABLE_LINK_TRAIN_MASK,
437                          NV_SWITCH_REGKEY_CCI_DISABLE_LINK_TRAIN_MASK_DEFAULT);
438     NVSWITCH_INIT_REGKEY(_PRIVATE, cci_link_train_disable_mask2,
439                          NV_SWITCH_REGKEY_CCI_DISABLE_LINK_TRAIN_MASK2,
440                          NV_SWITCH_REGKEY_CCI_DISABLE_LINK_TRAIN_MASK2_DEFAULT);
441     NVSWITCH_INIT_REGKEY(_PUBLIC, cci_max_onboard_attempts,
442                          NV_SWITCH_REGKEY_CCI_MAX_ONBOARD_ATTEMPTS,
443                          NV_SWITCH_REGKEY_CCI_MAX_ONBOARD_ATTEMPTS_DEFAULT);
444     NVSWITCH_INIT_REGKEY(_PUBLIC, cci_error_log_enable,
445                          NV_SWITCH_REGKEY_CCI_ERROR_LOG_ENABLE,
446                          NV_SWITCH_REGKEY_CCI_ERROR_LOG_ENABLE_DEFAULT);
447     //
448     // Debug use regkeys
449     // Not available on release build kernel drivers
450     //
451     NVSWITCH_INIT_REGKEY(_PRIVATE, external_fabric_mgmt,
452                          NV_SWITCH_REGKEY_EXTERNAL_FABRIC_MGMT,
453                          NV_SWITCH_REGKEY_EXTERNAL_FABRIC_MGMT_ENABLE);
454 
455     NVSWITCH_INIT_REGKEY(_PRIVATE, txtrain_control,
456                          NV_SWITCH_REGKEY_TXTRAIN_CONTROL,
457                          NV_SWITCH_REGKEY_TXTRAIN_CONTROL_NOP);
458 
459     NVSWITCH_INIT_REGKEY(_PRIVATE, crossbar_DBI,
460                          NV_SWITCH_REGKEY_CROSSBAR_DBI,
461                          NV_SWITCH_REGKEY_CROSSBAR_DBI_ENABLE);
462 
463     NVSWITCH_INIT_REGKEY(_PRIVATE, link_DBI,
464                          NV_SWITCH_REGKEY_LINK_DBI,
465                          NV_SWITCH_REGKEY_LINK_DBI_ENABLE);
466 
467     NVSWITCH_INIT_REGKEY(_PRIVATE, ac_coupled_mask,
468                          NV_SWITCH_REGKEY_AC_COUPLED_MASK,
469                          0);
470 
471     NVSWITCH_INIT_REGKEY(_PRIVATE, ac_coupled_mask2,
472                          NV_SWITCH_REGKEY_AC_COUPLED_MASK2,
473                          0);
474 
475     NVSWITCH_INIT_REGKEY(_PRIVATE, swap_clk,
476                          NV_SWITCH_REGKEY_SWAP_CLK_OVERRIDE,
477                          nvswitch_get_swap_clk_default(device));
478 
479     NVSWITCH_INIT_REGKEY(_PRIVATE, link_enable_mask,
480                          NV_SWITCH_REGKEY_ENABLE_LINK_MASK,
481                          NV_U32_MAX);
482 
483     NVSWITCH_INIT_REGKEY(_PRIVATE, link_enable_mask2,
484                          NV_SWITCH_REGKEY_ENABLE_LINK_MASK2,
485                          NV_U32_MAX);
486 
487     NVSWITCH_INIT_REGKEY(_PRIVATE, bandwidth_shaper,
488                          NV_SWITCH_REGKEY_BANDWIDTH_SHAPER,
489                          NV_SWITCH_REGKEY_BANDWIDTH_SHAPER_PROD);
490 
491     NVSWITCH_INIT_REGKEY(_PRIVATE, ssg_control,
492                          NV_SWITCH_REGKEY_SSG_CONTROL,
493                          0);
494 
495     NVSWITCH_INIT_REGKEY(_PRIVATE, skip_buffer_ready,
496                          NV_SWITCH_REGKEY_SKIP_BUFFER_READY,
497                          0);
498 
499     NVSWITCH_INIT_REGKEY(_PUBLIC, enable_pm,
500                          NV_SWITCH_REGKEY_ENABLE_PM,
501                          NV_SWITCH_REGKEY_ENABLE_PM_YES);
502 
503     NVSWITCH_INIT_REGKEY(_PRIVATE, chiplib_forced_config_link_mask,
504                          NV_SWITCH_REGKEY_CHIPLIB_FORCED_LINK_CONFIG_MASK,
505                          0);
506 
507     NVSWITCH_INIT_REGKEY(_PRIVATE, chiplib_forced_config_link_mask2,
508                          NV_SWITCH_REGKEY_CHIPLIB_FORCED_LINK_CONFIG_MASK2,
509                          0);
510 
511     NVSWITCH_INIT_REGKEY(_PRIVATE, soe_dma_self_test,
512                          NV_SWITCH_REGKEY_SOE_DMA_SELFTEST,
513                          NV_SWITCH_REGKEY_SOE_DMA_SELFTEST_ENABLE);
514 
515     NVSWITCH_INIT_REGKEY(_PRIVATE, soe_disable,
516                          NV_SWITCH_REGKEY_SOE_DISABLE,
517                          NV_SWITCH_REGKEY_SOE_DISABLE_NO);
518 
519     NVSWITCH_INIT_REGKEY(_PRIVATE, latency_counter,
520                          NV_SWITCH_REGKEY_LATENCY_COUNTER_LOGGING,
521                          NV_SWITCH_REGKEY_LATENCY_COUNTER_LOGGING_ENABLE);
522 
523     NVSWITCH_INIT_REGKEY(_PRIVATE, nvlink_speed_control,
524                          NV_SWITCH_REGKEY_SPEED_CONTROL,
525                          NV_SWITCH_REGKEY_SPEED_CONTROL_SPEED_DEFAULT);
526 
527     NVSWITCH_INIT_REGKEY(_PRIVATE, inforom_bbx_periodic_flush,
528                          NV_SWITCH_REGKEY_INFOROM_BBX_ENABLE_PERIODIC_FLUSHING,
529                          NV_SWITCH_REGKEY_INFOROM_BBX_ENABLE_PERIODIC_FLUSHING_DISABLE);
530 
531     NVSWITCH_INIT_REGKEY(_PRIVATE, inforom_bbx_write_periodicity,
532                          NV_SWITCH_REGKEY_INFOROM_BBX_WRITE_PERIODICITY,
533                          NV_SWITCH_REGKEY_INFOROM_BBX_WRITE_PERIODICITY_DEFAULT);
534 
535     NVSWITCH_INIT_REGKEY(_PRIVATE, inforom_bbx_write_min_duration,
536                          NV_SWITCH_REGKEY_INFOROM_BBX_WRITE_MIN_DURATION,
537                          NV_SWITCH_REGKEY_INFOROM_BBX_WRITE_MIN_DURATION_DEFAULT);
538 
539     NVSWITCH_INIT_REGKEY(_PRIVATE, minion_disable,
540                          NV_SWITCH_REGKEY_MINION_DISABLE,
541                          NV_SWITCH_REGKEY_MINION_DISABLE_NO);
542 
543     NVSWITCH_INIT_REGKEY(_PRIVATE, set_ucode_target,
544                          NV_SWITCH_REGKEY_MINION_SET_UCODE_TARGET,
545                          NV_SWITCH_REGKEY_MINION_SET_UCODE_TARGET_DEFAULT);
546 
547     NVSWITCH_INIT_REGKEY(_PRIVATE, set_simmode,
548                          NV_SWITCH_REGKEY_MINION_SET_SIMMODE,
549                          NV_SWITCH_REGKEY_MINION_SET_SIMMODE_DEFAULT);
550 
551     NVSWITCH_INIT_REGKEY(_PRIVATE, set_smf_settings,
552                          NV_SWITCH_REGKEY_MINION_SET_SMF_SETTINGS,
553                          NV_SWITCH_REGKEY_MINION_SET_SMF_SETTINGS_DEFAULT);
554 
555     NVSWITCH_INIT_REGKEY(_PRIVATE, select_uphy_tables,
556                          NV_SWITCH_REGKEY_MINION_SELECT_UPHY_TABLES,
557                          NV_SWITCH_REGKEY_MINION_SELECT_UPHY_TABLES_DEFAULT);
558 
559     NVSWITCH_INIT_REGKEY(_PRIVATE, link_training_mode,
560                          NV_SWITCH_REGKEY_LINK_TRAINING_SELECT,
561                          NV_SWITCH_REGKEY_LINK_TRAINING_SELECT_DEFAULT);
562 
563     NVSWITCH_INIT_REGKEY(_PRIVATE, i2c_access_control,
564                          NV_SWITCH_REGKEY_I2C_ACCESS_CONTROL,
565                          NV_SWITCH_REGKEY_I2C_ACCESS_CONTROL_DEFAULT);
566 
567     NVSWITCH_INIT_REGKEY(_PRIVATE, force_kernel_i2c,
568                          NV_SWITCH_REGKEY_FORCE_KERNEL_I2C,
569                          NV_SWITCH_REGKEY_FORCE_KERNEL_I2C_DEFAULT);
570 
571     NVSWITCH_INIT_REGKEY(_PRIVATE, link_recal_settings,
572                          NV_SWITCH_REGKEY_LINK_RECAL_SETTINGS,
573                          NV_SWITCH_REGKEY_LINK_RECAL_SETTINGS_NOP);
574 
575     NVSWITCH_INIT_REGKEY(_PRIVATE, lp_threshold,
576                          NV_SWITCH_REGKEY_SET_LP_THRESHOLD,
577                          NV_SWITCH_REGKEY_SET_LP_THRESHOLD_DEFAULT);
578 
579     NVSWITCH_INIT_REGKEY(_PUBLIC, minion_intr,
580                          NV_SWITCH_REGKEY_MINION_INTERRUPTS,
581                          NV_SWITCH_REGKEY_MINION_INTERRUPTS_DEFAULT);
582 
583     NVSWITCH_INIT_REGKEY(_PRIVATE, block_code_mode,
584                          NV_SWITCH_REGKEY_BLOCK_CODE_MODE,
585                          NV_SWITCH_REGKEY_BLOCK_CODE_MODE_DEFAULT);
586 
587     NVSWITCH_INIT_REGKEY(_PRIVATE, reference_clock_mode,
588                          NV_SWITCH_REGKEY_REFERENCE_CLOCK_MODE,
589                          NV_SWITCH_REGKEY_REFERENCE_CLOCK_MODE_DEFAULT);
590 
591     NVSWITCH_INIT_REGKEY(_PRIVATE, debug_level,
592                          NV_SWITCH_REGKEY_DBG_LEVEL,
593                          NV_SWITCH_REGKEY_DBG_LEVEL_DEFAULT);
594 }
595 
596 ct_assert(NVSWITCH_DBG_LEVEL_MMIO == NV_SWITCH_REGKEY_DBG_LEVEL_MMIO);
597 ct_assert(NVSWITCH_DBG_LEVEL_NOISY == NV_SWITCH_REGKEY_DBG_LEVEL_NOISY);
598 ct_assert(NVSWITCH_DBG_LEVEL_SETUP == NV_SWITCH_REGKEY_DBG_LEVEL_SETUP);
599 ct_assert(NVSWITCH_DBG_LEVEL_INFO == NV_SWITCH_REGKEY_DBG_LEVEL_INFO);
600 ct_assert(NVSWITCH_DBG_LEVEL_WARN == NV_SWITCH_REGKEY_DBG_LEVEL_WARN);
601 ct_assert(NVSWITCH_DBG_LEVEL_ERROR == NV_SWITCH_REGKEY_DBG_LEVEL_ERROR);
602 
603 NvU64
nvswitch_lib_deferred_task_dispatcher(nvswitch_device * device)604 nvswitch_lib_deferred_task_dispatcher
605 (
606     nvswitch_device *device
607 )
608 {
609     NvU64 time_nsec;
610     NvU64 time_next_nsec = nvswitch_os_get_platform_time() + 100*NVSWITCH_INTERVAL_1MSEC_IN_NS;
611     NVSWITCH_TASK_TYPE *task;
612     NVSWITCH_TASK_TYPE *prev_task;
613 
614     if (!NVSWITCH_IS_DEVICE_VALID(device))
615     {
616         return NV_U64_MAX;
617     }
618 
619     prev_task = NULL;
620     task = device->tasks;
621 
622     // Walk the task list, executing those whose next execution interval is at hand
623     while (task)
624     {
625         // Get current time (nsec) for scheduling
626         time_nsec = nvswitch_os_get_platform_time();
627 
628         if (time_nsec >= task->last_run_nsec + task->period_nsec)
629         {
630             //
631             // The task has never been run or it is time to run
632             // Mark its last run time
633             //
634             task->last_run_nsec = time_nsec;
635             // Run the task
636             if (NVSWITCH_IS_DEVICE_INITIALIZED(device) ||
637                (task->flags & NVSWITCH_TASK_TYPE_FLAGS_RUN_EVEN_IF_DEVICE_NOT_INITIALIZED))
638             {
639                 if(task->flags & NVSWITCH_TASK_TYPE_FLAGS_VOID_PTR_ARGS)
640                     (*task->task_fn_vdptr)(device, task->task_args);  // run task with provided args
641                 else
642                     (*task->task_fn_devptr)(device);
643             }
644         }
645 
646         // Determine its next run time
647         time_next_nsec = NV_MIN(task->last_run_nsec + task->period_nsec, time_next_nsec);
648 
649         // Advance pointer. If run once flag is set and task ran, remove task from list.
650         if((task->flags & NVSWITCH_TASK_TYPE_FLAGS_RUN_ONCE) &&
651            (task->last_run_nsec == time_nsec))
652         {
653             prev_task = task->prev;
654 
655             // Removing from list head
656             if (prev_task == NULL)
657             {
658                 device->tasks = task->next;
659                 if (device->tasks != NULL)
660                 {
661                     device->tasks->prev = NULL;
662                 }
663                 nvswitch_os_free(task);
664                 task = device->tasks;
665             }
666             else
667             {
668                 prev_task->next = task->next;
669                 if (prev_task->next != NULL)
670                 {
671                     prev_task->next->prev = prev_task;
672                 }
673                 nvswitch_os_free(task);
674                 task = prev_task->next;
675             }
676         }
677         else
678         {
679             task = task->next;
680         }
681     }
682 
683     time_nsec = nvswitch_os_get_platform_time();
684 
685     // Return to the OS layer how long to wait before calling again
686     return(time_next_nsec >= time_nsec ? time_next_nsec - time_nsec : 0);
687 }
688 
689 static NvlStatus
_nvswitch_setup_hal(nvswitch_device * device,NvU32 pci_device_id)690 _nvswitch_setup_hal
691 (
692     nvswitch_device *device,
693     NvU32 pci_device_id
694 )
695 {
696     if (nvswitch_is_lr10_device_id(pci_device_id))
697     {
698         nvswitch_setup_hal_lr10(device);
699         return NVL_SUCCESS;
700     }
701     if (nvswitch_is_ls10_device_id(pci_device_id))
702     {
703         nvswitch_setup_hal_ls10(device);
704         return NVL_SUCCESS;
705     }
706     NVSWITCH_PRINT(device, ERROR,
707         "NVSwitch HAL setup failed - Unrecognized PCI Device ID\n");
708     return -NVL_ERR_NOT_SUPPORTED;
709 }
710 
711 NvlStatus
nvswitch_lib_check_api_version(const char * user_version,char * kernel_version,NvU32 length)712 nvswitch_lib_check_api_version
713 (
714     const char *user_version,
715     char *kernel_version,
716     NvU32 length
717 )
718 {
719     const NvLength VERSION_LENGTH = nvswitch_os_strlen(NV_VERSION_STRING);
720 
721     if (kernel_version == NULL || user_version == NULL)
722     {
723         return -NVL_BAD_ARGS;
724     }
725 
726     if (length < VERSION_LENGTH)
727     {
728         return -NVL_NO_MEM;
729     }
730 
731     nvswitch_os_memset(kernel_version, 0x0, length);
732     nvswitch_os_strncpy(kernel_version, NV_VERSION_STRING, VERSION_LENGTH);
733 
734     kernel_version[length - 1] = '\0';
735 
736     if (nvswitch_os_strncmp(user_version, kernel_version, VERSION_LENGTH))
737     {
738         return -NVL_ERR_NOT_SUPPORTED;
739     }
740 
741     return NVL_SUCCESS;
742 }
743 
744 NvBool
nvswitch_is_inforom_supported(nvswitch_device * device)745 nvswitch_is_inforom_supported
746 (
747     nvswitch_device *device
748 )
749 {
750     return device->hal.nvswitch_is_inforom_supported(device);
751 }
752 
753 NvBool
nvswitch_is_spi_supported(nvswitch_device * device)754 nvswitch_is_spi_supported
755 (
756     nvswitch_device *device
757 )
758 {
759     return device->hal.nvswitch_is_spi_supported(device);
760 }
761 
762 NvBool
nvswitch_is_bios_supported(nvswitch_device * device)763 nvswitch_is_bios_supported
764 (
765     nvswitch_device *device
766 )
767 {
768     return device->hal.nvswitch_is_bios_supported(device);
769 }
770 
771 NvBool
nvswitch_is_smbpbi_supported(nvswitch_device * device)772 nvswitch_is_smbpbi_supported
773 (
774     nvswitch_device *device
775 )
776 {
777     return device->hal.nvswitch_is_smbpbi_supported(device);
778 }
779 
780 NvBool
nvswitch_is_soe_supported(nvswitch_device * device)781 nvswitch_is_soe_supported
782 (
783     nvswitch_device *device
784 )
785 {
786     return device->hal.nvswitch_is_soe_supported(device);
787 }
788 
789 
790 NvlStatus
nvswitch_init_soe(nvswitch_device * device)791 nvswitch_init_soe
792 (
793     nvswitch_device *device
794 )
795 {
796     return device->hal.nvswitch_init_soe(device);
797 }
798 
799 void
nvswitch_soe_init_l2_state(nvswitch_device * device)800 nvswitch_soe_init_l2_state
801 (
802     nvswitch_device *device
803 )
804 {
805     device->hal.nvswitch_soe_init_l2_state(device);
806 }
807 
808 void
nvswitch_fsp_update_cmdq_head_tail(nvswitch_device * device,NvU32 queueHead,NvU32 queueTail)809 nvswitch_fsp_update_cmdq_head_tail
810 (
811     nvswitch_device *device,
812     NvU32 queueHead,
813     NvU32 queueTail
814 )
815 {
816     return device->hal.nvswitch_fsp_update_cmdq_head_tail(device, queueHead, queueTail);
817 }
818 
819 void
nvswitch_fsp_get_cmdq_head_tail(nvswitch_device * device,NvU32 * pQueueHead,NvU32 * pQueueTail)820 nvswitch_fsp_get_cmdq_head_tail
821 (
822     nvswitch_device *device,
823     NvU32 *pQueueHead,
824     NvU32 *pQueueTail
825 )
826 {
827     return device->hal.nvswitch_fsp_get_cmdq_head_tail(device, pQueueHead, pQueueTail);
828 }
829 
830 void
nvswitch_fsp_update_msgq_head_tail(nvswitch_device * device,NvU32 msgqHead,NvU32 msgqTail)831 nvswitch_fsp_update_msgq_head_tail
832 (
833     nvswitch_device *device,
834     NvU32 msgqHead,
835     NvU32 msgqTail
836 )
837 {
838     return device->hal.nvswitch_fsp_update_msgq_head_tail(device, msgqHead, msgqTail);
839 }
840 
841 void
nvswitch_fsp_get_msgq_head_tail(nvswitch_device * device,NvU32 * pMsgqHead,NvU32 * pMsgqTail)842 nvswitch_fsp_get_msgq_head_tail
843 (
844     nvswitch_device *device,
845     NvU32 *pMsgqHead,
846     NvU32 *pMsgqTail
847 )
848 {
849    return device->hal.nvswitch_fsp_get_msgq_head_tail(device, pMsgqHead, pMsgqTail);
850 }
851 
852 NvU32
nvswitch_fsp_get_channel_size(nvswitch_device * device)853 nvswitch_fsp_get_channel_size
854 (
855     nvswitch_device *device
856 )
857 {
858     return device->hal.nvswitch_fsp_get_channel_size(device);
859 }
860 
861 NvU8
nvswitch_fsp_nvdm_to_seid(nvswitch_device * device,NvU8 nvdmType)862 nvswitch_fsp_nvdm_to_seid
863 (
864     nvswitch_device *device,
865     NvU8 nvdmType
866 )
867 {
868     return device->hal.nvswitch_fsp_nvdm_to_seid(device, nvdmType);
869 }
870 
871 NvU32
nvswitch_fsp_create_mctp_header(nvswitch_device * device,NvU8 som,NvU8 eom,NvU8 seid,NvU8 seq)872 nvswitch_fsp_create_mctp_header
873 (
874     nvswitch_device *device,
875     NvU8 som,
876     NvU8 eom,
877     NvU8 seid,
878     NvU8 seq
879 )
880 {
881     return device->hal.nvswitch_fsp_create_mctp_header(device, som, eom, seid, seq);
882 }
883 
884 NvU32
nvswitch_fsp_create_nvdm_header(nvswitch_device * device,NvU32 nvdmType)885 nvswitch_fsp_create_nvdm_header
886 (
887     nvswitch_device *device,
888     NvU32 nvdmType
889 )
890 {
891     return device->hal.nvswitch_fsp_create_nvdm_header(device, nvdmType);
892 }
893 
894 NvlStatus
nvswitch_fsp_get_packet_info(nvswitch_device * device,NvU8 * pBuffer,NvU32 size,NvU8 * pPacketState,NvU8 * pTag)895 nvswitch_fsp_get_packet_info
896 (
897     nvswitch_device *device,
898     NvU8 *pBuffer,
899     NvU32 size,
900     NvU8 *pPacketState,
901     NvU8 *pTag
902 )
903 {
904     return device->hal.nvswitch_fsp_get_packet_info(device, pBuffer, size, pPacketState, pTag);
905 }
906 
907 NvlStatus
nvswitch_fsp_validate_mctp_payload_header(nvswitch_device * device,NvU8 * pBuffer,NvU32 size)908 nvswitch_fsp_validate_mctp_payload_header
909 (
910     nvswitch_device  *device,
911     NvU8 *pBuffer,
912     NvU32 size
913 )
914 {
915     return device->hal.nvswitch_fsp_validate_mctp_payload_header(device, pBuffer, size);
916 }
917 
918 NvlStatus
nvswitch_fsp_process_nvdm_msg(nvswitch_device * device,NvU8 * pBuffer,NvU32 size)919 nvswitch_fsp_process_nvdm_msg
920 (
921     nvswitch_device *device,
922     NvU8 *pBuffer,
923     NvU32 size
924 )
925 {
926     return device->hal.nvswitch_fsp_process_nvdm_msg(device, pBuffer, size);
927 }
928 
929 NvlStatus
nvswitch_fsp_process_cmd_response(nvswitch_device * device,NvU8 * pBuffer,NvU32 size)930 nvswitch_fsp_process_cmd_response
931 (
932     nvswitch_device *device,
933     NvU8 *pBuffer,
934     NvU32 size
935 )
936 {
937     return device->hal.nvswitch_fsp_process_cmd_response(device, pBuffer, size);
938 }
939 
940 NvlStatus
nvswitch_fsp_config_ememc(nvswitch_device * device,NvU32 offset,NvBool bAincw,NvBool bAincr)941 nvswitch_fsp_config_ememc
942 (
943     nvswitch_device *device,
944     NvU32 offset,
945     NvBool bAincw,
946     NvBool bAincr
947 )
948 {
949     return device->hal.nvswitch_fsp_config_ememc(device, offset, bAincw, bAincr);
950 }
951 
952 NvlStatus
nvswitch_fsp_write_to_emem(nvswitch_device * device,NvU8 * pBuffer,NvU32 size)953 nvswitch_fsp_write_to_emem
954 (
955     nvswitch_device *device,
956     NvU8 *pBuffer,
957     NvU32 size
958 )
959 {
960     return device->hal.nvswitch_fsp_write_to_emem(device, pBuffer, size);
961 }
962 
963 NvlStatus
nvswitch_fsp_read_from_emem(nvswitch_device * device,NvU8 * pBuffer,NvU32 size)964 nvswitch_fsp_read_from_emem
965 (
966     nvswitch_device *device,
967     NvU8 *pBuffer,
968     NvU32 size
969 )
970 {
971     return device->hal.nvswitch_fsp_read_from_emem(device, pBuffer, size);
972 }
973 
974 NvlStatus
nvswitch_fsp_error_code_to_nvlstatus_map(nvswitch_device * device,NvU32 errorCode)975 nvswitch_fsp_error_code_to_nvlstatus_map
976 (
977     nvswitch_device *device,
978     NvU32 errorCode
979 )
980 {
981     return device->hal.nvswitch_fsp_error_code_to_nvlstatus_map(device, errorCode);
982 }
983 
984 static NvlStatus
_nvswitch_ctrl_fsprpc_get_caps(nvswitch_device * device,NVSWITCH_FSPRPC_GET_CAPS_PARAMS * params)985 _nvswitch_ctrl_fsprpc_get_caps
986 (
987     nvswitch_device *device,
988     NVSWITCH_FSPRPC_GET_CAPS_PARAMS *params
989 )
990 {
991     return device->hal.nvswitch_fsprpc_get_caps(device, params);
992 }
993 
994 static NvlStatus
_nvswitch_ctrl_get_attestation_certificate_chain(nvswitch_device * device,NVSWITCH_GET_ATTESTATION_CERTIFICATE_CHAIN_PARAMS * params)995 _nvswitch_ctrl_get_attestation_certificate_chain
996 (
997     nvswitch_device *device,
998     NVSWITCH_GET_ATTESTATION_CERTIFICATE_CHAIN_PARAMS *params
999 )
1000 {
1001     return device->hal.nvswitch_tnvl_get_attestation_certificate_chain(device, params);
1002 }
1003 
1004 static NvlStatus
_nvswitch_ctrl_get_attestation_report(nvswitch_device * device,NVSWITCH_GET_ATTESTATION_REPORT_PARAMS * params)1005 _nvswitch_ctrl_get_attestation_report
1006 (
1007     nvswitch_device *device,
1008     NVSWITCH_GET_ATTESTATION_REPORT_PARAMS *params
1009 )
1010 {
1011     return device->hal.nvswitch_tnvl_get_attestation_report(device, params);
1012 }
1013 
1014 static NvlStatus
_nvswitch_ctrl_get_tnvl_status(nvswitch_device * device,NVSWITCH_GET_TNVL_STATUS_PARAMS * params)1015 _nvswitch_ctrl_get_tnvl_status
1016 (
1017     nvswitch_device *device,
1018     NVSWITCH_GET_TNVL_STATUS_PARAMS *params
1019 )
1020 {
1021     return device->hal.nvswitch_tnvl_get_status(device, params);
1022 }
1023 
1024 static NvlStatus
_nvswitch_construct_soe(nvswitch_device * device)1025 _nvswitch_construct_soe
1026 (
1027     nvswitch_device *device
1028 )
1029 {
1030     FLCNABLE *pSoe = NULL;
1031     NvlStatus retval;
1032 
1033     device->pSoe = pSoe = (PFLCNABLE)soeAllocNew();
1034     if (pSoe == NULL)
1035     {
1036         NVSWITCH_PRINT(device, ERROR, "SOE allocation failed.\n");
1037         return -NVL_NO_MEM;
1038     }
1039 
1040     retval = soeInit(device, (PSOE)pSoe, device->nvlink_device->pciInfo.pciDeviceId);
1041     if (retval != NVL_SUCCESS)
1042     {
1043         NVSWITCH_PRINT(device, ERROR, "SOE init failed.\n");
1044         goto soe_init_failed;
1045     }
1046 
1047     if (flcnableConstruct_HAL(device, pSoe) != NV_OK)
1048     {
1049         NVSWITCH_PRINT(device, ERROR, "FALCON construct failed.\n");
1050         retval = -NVL_ERR_INVALID_STATE;
1051         goto flcn_construct_failed;
1052     }
1053 
1054     return NVL_SUCCESS;
1055 
1056 flcn_construct_failed:
1057     soeDestroy(device, (PSOE)pSoe);
1058 
1059 soe_init_failed:
1060     nvswitch_os_free(pSoe);
1061     device->pSoe = NULL;
1062 
1063     return retval;
1064 }
1065 
1066 static void
_nvswitch_destruct_soe(nvswitch_device * device)1067 _nvswitch_destruct_soe
1068 (
1069     nvswitch_device *device
1070 )
1071 {
1072     FLCNABLE *pSoe = device->pSoe;
1073 
1074     if (pSoe == NULL)
1075     {
1076         return;
1077     }
1078 
1079     flcnableDestruct_HAL(device, pSoe);
1080     soeDestroy(device, (PSOE)pSoe);
1081 
1082     nvswitch_os_free(pSoe);
1083     device->pSoe = NULL;
1084 }
1085 
1086 static NvlStatus
_nvswitch_construct_cci(nvswitch_device * device)1087 _nvswitch_construct_cci
1088 (
1089     nvswitch_device *device
1090 )
1091 {
1092     CCI *pCci = NULL;
1093     NvlStatus retval;
1094 
1095     device->pCci = pCci = cciAllocNew();
1096     if (pCci == NULL)
1097     {
1098         NVSWITCH_PRINT(device, ERROR, "CCI allocation failed.\n");
1099         return -NVL_NO_MEM;
1100     }
1101 
1102     retval = cciInit(device, pCci, device->nvlink_device->pciInfo.pciDeviceId);
1103     if (retval != NVL_SUCCESS)
1104     {
1105         NVSWITCH_PRINT(device, ERROR, "CCI init failed.\n");
1106         goto cci_init_failed;
1107     }
1108 
1109     return NVL_SUCCESS;
1110 
1111 cci_init_failed:
1112     nvswitch_os_free(pCci);
1113     device->pCci = NULL;
1114 
1115     return retval;
1116 }
1117 
1118 static void
_nvswitch_destruct_cci(nvswitch_device * device)1119 _nvswitch_destruct_cci
1120 (
1121     nvswitch_device *device
1122 )
1123 {
1124     CCI *pCci = device->pCci;
1125 
1126     if (pCci == NULL)
1127     {
1128         return;
1129     }
1130 
1131     cciDestroy(device, pCci);
1132 
1133     nvswitch_os_free(pCci);
1134     device->pCci = NULL;
1135 }
1136 
1137 static void
_nvswitch_update_link_state_led(nvswitch_device * device)1138 _nvswitch_update_link_state_led
1139 (
1140     nvswitch_device *device
1141 )
1142 {
1143     device->hal.nvswitch_update_link_state_led(device);
1144 }
1145 
1146 static void
_nvswitch_led_shutdown(nvswitch_device * device)1147 _nvswitch_led_shutdown
1148 (
1149     nvswitch_device *device
1150 )
1151 {
1152     device->hal.nvswitch_led_shutdown(device);
1153 }
1154 
1155 static NvlStatus
_nvswitch_initialize_device_state(nvswitch_device * device)1156 _nvswitch_initialize_device_state
1157 (
1158     nvswitch_device *device
1159 )
1160 {
1161     return device->hal.nvswitch_initialize_device_state(device);
1162 }
1163 
1164 static NvlStatus
_nvswitch_post_init_device_setup(nvswitch_device * device)1165 _nvswitch_post_init_device_setup
1166 (
1167     nvswitch_device *device
1168 )
1169 {
1170     return device->hal.nvswitch_post_init_device_setup(device);
1171 }
1172 
1173 static NvlStatus
_nvswitch_setup_system_registers(nvswitch_device * device)1174 _nvswitch_setup_system_registers
1175 (
1176     nvswitch_device *device
1177 )
1178 {
1179     return device->hal.nvswitch_setup_system_registers(device);
1180 }
1181 
1182 static void
_nvswitch_post_init_blacklist_device_setup(nvswitch_device * device)1183 _nvswitch_post_init_blacklist_device_setup
1184 (
1185     nvswitch_device *device
1186 )
1187 {
1188     device->hal.nvswitch_post_init_blacklist_device_setup(device);
1189 }
1190 
1191 static void
_nvswitch_set_dma_mask(nvswitch_device * device)1192 _nvswitch_set_dma_mask
1193 (
1194     nvswitch_device *device
1195 )
1196 {
1197     NvU32 hw_dma_width, retval;
1198 
1199     hw_dma_width = device->hal.nvswitch_get_device_dma_width(device);
1200 
1201     if (hw_dma_width == 0)
1202     {
1203         NVSWITCH_PRINT(device, INFO, "DMA is not supported on this device\n");
1204         return;
1205     }
1206 
1207     retval = nvswitch_os_set_dma_mask(device->os_handle, hw_dma_width);
1208     if (retval == NVL_SUCCESS)
1209     {
1210         device->dma_addr_width = hw_dma_width;
1211         return;
1212     }
1213 
1214     NVSWITCH_PRINT(device, SETUP,
1215                    "%s: Failed to set DMA mask, trying 32-bit fallback : %d\n",
1216                    __FUNCTION__, retval);
1217 
1218     retval = nvswitch_os_set_dma_mask(device->os_handle, 32);
1219     if (retval == NVL_SUCCESS)
1220     {
1221         device->dma_addr_width = 32;
1222         return;
1223     }
1224 
1225     // failure is not fatal, the driver will just restrict DMA functionality
1226     NVSWITCH_PRINT(device, ERROR, "Failed to set DMA mask : %d\n", retval);
1227 }
1228 
1229 NvlStatus
nvswitch_deassert_link_reset(nvswitch_device * device,nvlink_link * link)1230 nvswitch_deassert_link_reset
1231 (
1232     nvswitch_device *device,
1233     nvlink_link *link
1234 )
1235 {
1236     return device->hal.nvswitch_deassert_link_reset(device, link);
1237 }
1238 
1239 NvU32
nvswitch_get_sublink_width(nvswitch_device * device,NvU32 linkNumber)1240 nvswitch_get_sublink_width
1241 (
1242     nvswitch_device *device,
1243     NvU32 linkNumber
1244 )
1245 {
1246     return device->hal.nvswitch_get_sublink_width(device, linkNumber);
1247 }
1248 
1249 static void
_nvswitch_unregister_links(nvswitch_device * device)1250 _nvswitch_unregister_links
1251 (
1252     nvswitch_device *device
1253 )
1254 {
1255     nvlink_link *link = NULL;
1256     NvU32 link_num;
1257     NvBool is_blacklisted;
1258 
1259 
1260     if (!NVSWITCH_IS_DEVICE_INITIALIZED(device))
1261         return;
1262 
1263     device->nvlink_device->initialized = 0;
1264     is_blacklisted = (device->device_fabric_state == NVSWITCH_DEVICE_FABRIC_STATE_BLACKLISTED);
1265 
1266     for (link_num = 0; link_num < nvswitch_get_num_links(device); link_num++)
1267     {
1268         if (nvlink_lib_get_link(device->nvlink_device, link_num, &link) == NVL_SUCCESS)
1269         {
1270             nvlink_lib_unregister_link(link);
1271             nvswitch_destroy_link(link);
1272         }
1273     }
1274 
1275     if (!is_blacklisted)
1276         nvswitch_inforom_nvlink_flush(device);
1277 }
1278 
1279 NvlStatus NV_API_CALL
nvswitch_lib_read_fabric_state(nvswitch_device * device,NVSWITCH_DEVICE_FABRIC_STATE * device_fabric_state,NVSWITCH_DEVICE_BLACKLIST_REASON * device_blacklist_reason,NVSWITCH_DRIVER_FABRIC_STATE * driver_fabric_state)1280 nvswitch_lib_read_fabric_state
1281 (
1282     nvswitch_device *device,
1283     NVSWITCH_DEVICE_FABRIC_STATE *device_fabric_state,
1284     NVSWITCH_DEVICE_BLACKLIST_REASON *device_blacklist_reason,
1285     NVSWITCH_DRIVER_FABRIC_STATE *driver_fabric_state
1286 )
1287 {
1288     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1289         return -NVL_BAD_ARGS;
1290 
1291     if (device_fabric_state != NULL)
1292         *device_fabric_state = device->device_fabric_state;
1293 
1294     if (device_blacklist_reason != NULL)
1295         *device_blacklist_reason = device->device_blacklist_reason;
1296 
1297     if (driver_fabric_state != NULL)
1298         *driver_fabric_state = device->driver_fabric_state;
1299 
1300     return NVL_SUCCESS;
1301 }
1302 
1303 static NvlStatus
nvswitch_lib_blacklist_device(nvswitch_device * device,NVSWITCH_DEVICE_BLACKLIST_REASON device_blacklist_reason)1304 nvswitch_lib_blacklist_device
1305 (
1306     nvswitch_device *device,
1307     NVSWITCH_DEVICE_BLACKLIST_REASON device_blacklist_reason
1308 )
1309 {
1310     NvlStatus status;
1311 
1312     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1313     {
1314         return -NVL_BAD_ARGS;
1315     }
1316 
1317     if (device->device_fabric_state == NVSWITCH_DEVICE_FABRIC_STATE_BLACKLISTED)
1318     {
1319         NVSWITCH_PRINT(device, WARN, "Device is already blacklisted\n");
1320         return -NVL_ERR_NOT_SUPPORTED;
1321     }
1322 
1323     device->device_fabric_state = NVSWITCH_DEVICE_FABRIC_STATE_BLACKLISTED;
1324     device->device_blacklist_reason = device_blacklist_reason;
1325 
1326     status = device->hal.nvswitch_write_fabric_state(device);
1327     if (status != NVL_SUCCESS)
1328         NVSWITCH_PRINT(device, INFO, "Cannot send fabric state to SOE\n");
1329 
1330     return NVL_SUCCESS;
1331 }
1332 
1333 static NvlStatus
nvswitch_ctrl_blacklist_device(nvswitch_device * device,NVSWITCH_BLACKLIST_DEVICE_PARAMS * p)1334 nvswitch_ctrl_blacklist_device(
1335     nvswitch_device *device,
1336     NVSWITCH_BLACKLIST_DEVICE_PARAMS *p
1337 )
1338 {
1339     NvlStatus status;
1340 
1341     status = nvswitch_lib_blacklist_device(device, p->deviceReason);
1342     if (status != NVL_SUCCESS)
1343         return status;
1344 
1345     nvswitch_lib_disable_interrupts(device);
1346 
1347     // Unregister links from NVLinkCoreLib, so that link training is not
1348     // attempted
1349     _nvswitch_unregister_links(device);
1350 
1351     // Keep device registered for HAL access and Fabric State updates
1352 
1353     return NVL_SUCCESS;
1354 }
1355 
1356 static NvlStatus
nvswitch_ctrl_set_fm_driver_state(nvswitch_device * device,NVSWITCH_SET_FM_DRIVER_STATE_PARAMS * p)1357 nvswitch_ctrl_set_fm_driver_state(
1358     nvswitch_device *device,
1359     NVSWITCH_SET_FM_DRIVER_STATE_PARAMS *p
1360 )
1361 {
1362     NvU32 prev_fm_status;
1363 
1364     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1365     {
1366         return -NVL_BAD_ARGS;
1367     }
1368 
1369     prev_fm_status = device->driver_fabric_state;
1370     device->driver_fabric_state = p->driverState;
1371     device->fabric_state_timestamp = nvswitch_os_get_platform_time();
1372 
1373     if (prev_fm_status != p->driverState)
1374     {
1375         if (nvswitch_lib_notify_client_events(device,
1376             NVSWITCH_DEVICE_EVENT_FABRIC_STATE) != NVL_SUCCESS)
1377         {
1378             NVSWITCH_PRINT(device, ERROR, "%s: Failed to notify event\n",
1379                            __FUNCTION__);
1380         }
1381     }
1382 
1383     return NVL_SUCCESS;
1384 }
1385 
1386 static NvlStatus
nvswitch_ctrl_set_device_fabric_state(nvswitch_device * device,NVSWITCH_SET_DEVICE_FABRIC_STATE_PARAMS * p)1387 nvswitch_ctrl_set_device_fabric_state(
1388     nvswitch_device *device,
1389     NVSWITCH_SET_DEVICE_FABRIC_STATE_PARAMS *p
1390 )
1391 {
1392     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1393     {
1394         return -NVL_BAD_ARGS;
1395     }
1396 
1397     if (device->device_fabric_state == NVSWITCH_DEVICE_FABRIC_STATE_BLACKLISTED)
1398         return -NVL_ERR_NOT_SUPPORTED;
1399 
1400     device->device_fabric_state = p->deviceState;
1401     device->fabric_state_timestamp = nvswitch_os_get_platform_time();
1402 
1403     // If FM had exceeded timeout, reset the status to not timed-out
1404     if (device->driver_fabric_state == NVSWITCH_DRIVER_FABRIC_STATE_MANAGER_TIMEOUT)
1405         device->driver_fabric_state = NVSWITCH_DRIVER_FABRIC_STATE_CONFIGURED;
1406 
1407     return NVL_SUCCESS;
1408 }
1409 
1410 static NvlStatus
nvswitch_ctrl_set_fm_timeout(nvswitch_device * device,NVSWITCH_SET_FM_HEARTBEAT_TIMEOUT_PARAMS * p)1411 nvswitch_ctrl_set_fm_timeout(
1412     nvswitch_device *device,
1413     NVSWITCH_SET_FM_HEARTBEAT_TIMEOUT_PARAMS *p
1414 )
1415 {
1416     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1417     {
1418         return -NVL_BAD_ARGS;
1419     }
1420 
1421     device->fm_timeout = p->fmTimeout;
1422 
1423     return NVL_SUCCESS;
1424 }
1425 
1426 static NvlStatus
_nvswitch_ctrl_register_events(nvswitch_device * device,NVSWITCH_REGISTER_EVENTS_PARAMS * p,void * osPrivate)1427 _nvswitch_ctrl_register_events(
1428     nvswitch_device *device,
1429     NVSWITCH_REGISTER_EVENTS_PARAMS *p,
1430     void *osPrivate
1431 )
1432 {
1433     NvlStatus status = NVL_SUCCESS;
1434     NvU32 i;
1435     NvBool many_events, os_descriptor;
1436     void *osDescriptor = osPrivate;
1437 
1438     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1439     {
1440         return -NVL_BAD_ARGS;
1441     }
1442 
1443     status = nvswitch_os_get_supported_register_events_params(&many_events,
1444                                                               &os_descriptor);
1445     if (status != NVL_SUCCESS)
1446     {
1447         return status;
1448     }
1449 
1450     if ((!many_events && (p->numEvents > 1)) ||
1451         (p->numEvents == 0))
1452     {
1453         return -NVL_BAD_ARGS;
1454     }
1455 
1456     if (os_descriptor)
1457     {
1458         osDescriptor = (void *) p->osDescriptor;
1459     }
1460 
1461     for (i = 0; i < p->numEvents; i++)
1462     {
1463         status = nvswitch_lib_add_client_event(device, osDescriptor, p->eventIds[i]);
1464         if (status != NVL_SUCCESS)
1465         {
1466             NVSWITCH_PRINT(device, ERROR, "%s: Failed to add client event.\n", __FUNCTION__);
1467             return status;
1468         }
1469     }
1470 
1471     return NVL_SUCCESS;
1472 }
1473 
1474 static NvlStatus
_nvswitch_ctrl_unregister_events(nvswitch_device * device,NVSWITCH_UNREGISTER_EVENTS_PARAMS * p,void * osPrivate)1475 _nvswitch_ctrl_unregister_events(
1476     nvswitch_device *device,
1477     NVSWITCH_UNREGISTER_EVENTS_PARAMS *p,
1478     void *osPrivate
1479 )
1480 {
1481     NvlStatus status = NVL_SUCCESS;
1482     NvBool many_events, os_descriptor;
1483     void *osDescriptor = osPrivate;
1484 
1485     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1486     {
1487         return -NVL_BAD_ARGS;
1488     }
1489 
1490     status = nvswitch_os_get_supported_register_events_params(&many_events,
1491                                                               &os_descriptor);
1492     if (status != NVL_SUCCESS)
1493     {
1494         return status;
1495     }
1496 
1497     if (os_descriptor)
1498     {
1499         osDescriptor = (void *) p->osDescriptor;
1500     }
1501 
1502     status = nvswitch_lib_remove_client_events(device, osDescriptor);
1503     if (status != NVL_SUCCESS)
1504     {
1505         NVSWITCH_PRINT(device, ERROR, "%s: Failed to remove client event.\n", __FUNCTION__);
1506         return status;
1507     }
1508 
1509     return NVL_SUCCESS;
1510 }
1511 
1512 /*
1513  * @Brief : Sends NACK or drops given inband msg based on message type
1514  *
1515  * @Description :
1516  *
1517  * @param[in] device            NvSwitch device to contain this link
1518  * @param[in] linkId            Link ID
1519  * @param[in] msghdr            Header to the message
1520  *
1521  */
1522 static void
nvswitch_send_nack_or_drop(nvswitch_device * device,NvU32 linkId,nvlink_inband_msg_header_t * msghdr)1523 nvswitch_send_nack_or_drop
1524 (
1525     nvswitch_device            *device,
1526     NvU32                       linkId,
1527     nvlink_inband_msg_header_t *msghdr
1528 )
1529 {
1530     switch(msghdr->type)
1531     {
1532         case NVLINK_INBAND_MSG_TYPE_MC_TEAM_SETUP_REQ:
1533             device->hal.nvswitch_send_inband_nack(device, (NvU32 *)msghdr, linkId);
1534             NVSWITCH_PRINT(device, ERROR,
1535                            "Sending NACK for message (type 0x%x)\n", msghdr->type);
1536             return;
1537         default:
1538             // TODO: Add SXid in future if needed.
1539             NVSWITCH_PRINT(device, ERROR,
1540                            "Dropping message (type 0x%x)\n", msghdr->type);
1541             return;
1542     }
1543 }
1544 
1545 /*
1546  * @Brief : Deletes all the entries in persistent or non-persistent lists.
1547  *          Send nacks if requested.
1548  *
1549  * @Description :
1550  *
1551  * @param[in] device              NVSwitch device to contain this link
1552  * @param[in] linkId              Link number
1553  * @param[in] bSendNack           Send nacks if true
1554  * @param[in] bNonPersistentOnly  Clear only non-persistent list
1555  */
1556 static void
_nvswitch_inband_clear_lists(nvswitch_device * device,NvU32 linkId,NvBool bSendNack,NvBool bNonPersistentOnly)1557 _nvswitch_inband_clear_lists
1558 (
1559     nvswitch_device *device,
1560     NvU32            linkId,
1561     NvBool           bSendNack,
1562     NvBool           bNonPersistentOnly
1563 )
1564 {
1565     nvswitch_inband_data_list *curr = NULL;
1566     nvswitch_inband_data_list *next = NULL;
1567     nvlink_inband_msg_header_t *msghdr = NULL;
1568 
1569     nvListForEachEntry_safe(curr, next,
1570                     &device->link[linkId].inbandData.nonpersistent_list, entry)
1571     {
1572         if (bSendNack)
1573         {
1574             msghdr = (nvlink_inband_msg_header_t *)curr->data;
1575             nvswitch_send_nack_or_drop(device, linkId, msghdr);
1576         }
1577 
1578         nvListDel(&curr->entry);
1579         nvswitch_os_free(curr);
1580     }
1581 
1582     if (bNonPersistentOnly)
1583         return;
1584 
1585     nvListForEachEntry_safe(curr, next,
1586                     &device->link[linkId].inbandData.persistent_list, entry)
1587     {
1588         if (bSendNack)
1589         {
1590             msghdr = (nvlink_inband_msg_header_t *)curr->data;
1591             nvswitch_send_nack_or_drop(device, linkId, msghdr);
1592         }
1593 
1594         nvListDel(&curr->entry);
1595         nvswitch_os_free(curr);
1596     }
1597 }
1598 
1599 static void
nvswitch_fabric_state_heartbeat(nvswitch_device * device)1600 nvswitch_fabric_state_heartbeat(
1601     nvswitch_device *device
1602 )
1603 {
1604     NvU64 age;
1605     NvU32 linkId;
1606 
1607     if (!NVSWITCH_IS_DEVICE_VALID(device))
1608         return;
1609 
1610     age = nvswitch_os_get_platform_time() - device->fabric_state_timestamp;
1611 
1612     // Check to see if we have exceeded the FM timeout
1613     if (device->driver_fabric_state == NVSWITCH_DRIVER_FABRIC_STATE_CONFIGURED &&
1614         age > (NvU64)device->fm_timeout * 1000ULL * 1000ULL)
1615          device->driver_fabric_state = NVSWITCH_DRIVER_FABRIC_STATE_MANAGER_TIMEOUT;
1616 
1617     //
1618     // If FM is not running, clear pending non-persistent messages. Persistent
1619     // messages can be processed by the FM when it restarts.
1620     //
1621     if (device->driver_fabric_state != NVSWITCH_DRIVER_FABRIC_STATE_CONFIGURED)
1622     {
1623         for (linkId = 0; linkId < nvswitch_get_num_links(device); linkId++)
1624             _nvswitch_inband_clear_lists(device, linkId,
1625                                          NV_TRUE /* Nack */,
1626                                          NV_TRUE /* Non-persistent only */);
1627     }
1628 
1629     (void)device->hal.nvswitch_write_fabric_state(device);
1630 }
1631 
1632 static NvlStatus
_nvswitch_ctrl_set_training_error_info(nvswitch_device * device,NVSWITCH_SET_TRAINING_ERROR_INFO_PARAMS * p)1633 _nvswitch_ctrl_set_training_error_info
1634 (
1635     nvswitch_device *device,
1636     NVSWITCH_SET_TRAINING_ERROR_INFO_PARAMS *p
1637 )
1638 {
1639     return device->hal.nvswitch_set_training_error_info(device, p);
1640 }
1641 
1642 static NvlStatus
_nvswitch_ctrl_get_fatal_error_scope(nvswitch_device * device,NVSWITCH_GET_FATAL_ERROR_SCOPE_PARAMS * pParams)1643 _nvswitch_ctrl_get_fatal_error_scope
1644 (
1645     nvswitch_device *device,
1646     NVSWITCH_GET_FATAL_ERROR_SCOPE_PARAMS *pParams
1647 )
1648 {
1649     return device->hal.nvswitch_ctrl_get_fatal_error_scope(device, pParams);
1650 }
1651 
1652 static NvlStatus
_nvswitch_ctrl_therm_get_temperature_limit(nvswitch_device * device,NVSWITCH_CTRL_GET_TEMPERATURE_LIMIT_PARAMS * pParams)1653 _nvswitch_ctrl_therm_get_temperature_limit
1654 (
1655     nvswitch_device *device,
1656     NVSWITCH_CTRL_GET_TEMPERATURE_LIMIT_PARAMS *pParams
1657 )
1658 {
1659     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1660     {
1661         return -NVL_BAD_ARGS;
1662     }
1663 
1664     return device->hal.nvswitch_ctrl_therm_get_temperature_limit(device, pParams);
1665 }
1666 
1667 //
1668 // Construct an port event log
1669 //
1670 // If port_event_log_size > 0 a circular buffer is created to record port events
1671 //
1672 NvlStatus
_nvswitch_construct_port_event_log(NVSWITCH_PORT_EVENT_LOG_TYPE * port_events,NvU32 port_event_log_size,NvBool overwritable)1673 _nvswitch_construct_port_event_log
1674 (
1675     NVSWITCH_PORT_EVENT_LOG_TYPE *port_events,
1676     NvU32 port_event_log_size,
1677     NvBool overwritable
1678 )
1679 {
1680     NvlStatus retval = NVL_SUCCESS;
1681 
1682     NVSWITCH_ASSERT(port_events != NULL);
1683 
1684     port_events->port_event_start = 0;
1685     port_events->port_event_count = 0;
1686     port_events->port_event_total = 0;
1687     port_events->port_event_log_size = 0;
1688     port_events->port_event_log = NULL;
1689     port_events->overwritable = overwritable;
1690     port_events->bOverflow = NV_FALSE;
1691 
1692     if (port_event_log_size > 0)
1693     {
1694         port_events->port_event_log = nvswitch_os_malloc(port_event_log_size * sizeof(NVSWITCH_PORT_EVENT_TYPE));
1695     }
1696 
1697     if (port_events->port_event_log != NULL)
1698     {
1699         port_events->port_event_log_size = port_event_log_size;
1700         nvswitch_os_memset(port_events->port_event_log, 0, port_events->port_event_log_size * sizeof(NVSWITCH_PORT_EVENT_TYPE));
1701     }
1702 
1703     if (port_event_log_size != port_events->port_event_log_size)
1704     {
1705         retval = -NVL_NO_MEM;
1706     }
1707 
1708     return retval;
1709 }
1710 
1711 //
1712 // Destroy an error log
1713 //
1714 void
_nvswitch_destroy_port_event_log(nvswitch_device * device,NVSWITCH_PORT_EVENT_LOG_TYPE * port_events)1715 _nvswitch_destroy_port_event_log
1716 (
1717     nvswitch_device *device,
1718     NVSWITCH_PORT_EVENT_LOG_TYPE *port_events
1719 )
1720 {
1721     if (port_events == NULL)
1722         return;
1723 
1724     port_events->port_event_start = 0;
1725     port_events->port_event_count = 0;
1726     port_events->port_event_log_size = 0;
1727     port_events->bOverflow = NV_FALSE;
1728 
1729     if (port_events->port_event_log != NULL)
1730     {
1731         nvswitch_os_free(port_events->port_event_log);
1732         port_events->port_event_log = NULL;
1733     }
1734 }
1735 
1736 NvlStatus
nvswitch_lib_initialize_device(nvswitch_device * device)1737 nvswitch_lib_initialize_device
1738 (
1739     nvswitch_device *device
1740 )
1741 {
1742     NvlStatus retval = NVL_SUCCESS;
1743     NvU8 link_num;
1744     nvlink_link *link = NULL;
1745     NvBool is_blacklisted_by_os = NV_FALSE;
1746 
1747     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1748     {
1749         return -NVL_BAD_ARGS;
1750     }
1751 
1752     if (NVSWITCH_IS_DEVICE_INITIALIZED(device))
1753     {
1754         NVSWITCH_PRINT(device, SETUP, "Device is already initialized!\n");
1755         return NVL_SUCCESS;
1756     }
1757 
1758     NVSWITCH_PRINT(device, SETUP,
1759         "Initializing nvswitch at (%04x:%02x:%02x.%02x)\n",
1760         device->nvlink_device->pciInfo.domain,
1761         device->nvlink_device->pciInfo.bus,
1762         device->nvlink_device->pciInfo.device,
1763         device->nvlink_device->pciInfo.function);
1764 
1765     nvListInit(&device->client_events_list);
1766 
1767     for (link_num=0; link_num < nvswitch_get_num_links(device); link_num++)
1768     {
1769         nvListInit(&device->link[link_num].inbandData.persistent_list);
1770         nvListInit(&device->link[link_num].inbandData.nonpersistent_list);
1771     }
1772 
1773     retval = nvswitch_lib_load_platform_info(device);
1774     if (retval != NVL_SUCCESS)
1775     {
1776         NVSWITCH_PRINT(device, ERROR, "Failed to load platform information\n");
1777         return retval;
1778     }
1779 
1780     if (nvswitch_is_soe_supported(device))
1781     {
1782         retval = _nvswitch_construct_soe(device);
1783         if (retval != NVL_SUCCESS)
1784         {
1785             return retval;
1786         }
1787     }
1788     else
1789     {
1790         NVSWITCH_PRINT(device, INFO, "SOE is not supported, skipping construct\n");
1791     }
1792     if (nvswitch_is_cci_supported(device))
1793     {
1794         retval = _nvswitch_construct_cci(device);
1795         if (retval != NVL_SUCCESS)
1796         {
1797             NVSWITCH_PRINT(device, ERROR, "Failed to construct CCI: %d\n", retval);
1798             goto nvswitch_initialize_cci_fail;
1799         }
1800     }
1801     else
1802     {
1803         NVSWITCH_PRINT(device, INFO, "CCI is not supported, skipping construct\n");
1804     }
1805 
1806     _nvswitch_set_dma_mask(device);
1807 
1808     retval = _nvswitch_initialize_device_state(device);
1809     if (NVL_SUCCESS != retval)
1810     {
1811         NVSWITCH_PRINT(device, ERROR,
1812             "Failed to initialize device state: %d!\n",
1813             retval);
1814         goto nvswitch_initialize_device_state_fail;
1815     }
1816 
1817     device->hal.nvswitch_load_uuid(device);
1818 
1819     /*
1820      * Check module parameters for blacklisted device
1821      */
1822     if (nvswitch_os_is_uuid_in_blacklist(&device->uuid) == NV_TRUE)
1823     {
1824         NVSWITCH_PRINT(device, SETUP,
1825             "Blacklisted nvswitch at (%04x:%02x:%02x.%02x)\n",
1826             device->nvlink_device->pciInfo.domain,
1827             device->nvlink_device->pciInfo.bus,
1828             device->nvlink_device->pciInfo.device,
1829             device->nvlink_device->pciInfo.function);
1830         is_blacklisted_by_os = NV_TRUE;
1831         // initialization continues until we have updated InfoROM...
1832     }
1833 
1834     if (nvswitch_is_inforom_supported(device))
1835     {
1836         retval = nvswitch_initialize_inforom(device);
1837         if (NVL_SUCCESS != retval)
1838         {
1839             NVSWITCH_PRINT(device, ERROR,
1840                     "Failed to initialize InfoROM rc: %d\n",
1841                     retval);
1842             goto nvswitch_initialize_device_state_fail;
1843         }
1844 
1845         retval = nvswitch_initialize_inforom_objects(device);
1846         if (NVL_SUCCESS != retval)
1847         {
1848             NVSWITCH_PRINT(device, ERROR,
1849                         "Failed to initialize InfoROM objects! rc:%d\n",
1850                         retval);
1851             goto nvswitch_initialize_inforom_fail;
1852         }
1853     }
1854     else
1855     {
1856         NVSWITCH_PRINT(device, INFO,
1857                 "InfoROM is not supported, skipping init\n");
1858     }
1859 
1860     (void)device->hal.nvswitch_read_oob_blacklist_state(device);
1861     (void)device->hal.nvswitch_write_fabric_state(device);
1862 
1863     nvswitch_task_create(device, &nvswitch_fabric_state_heartbeat,
1864                          NVSWITCH_HEARTBEAT_INTERVAL_NS,
1865                          NVSWITCH_TASK_TYPE_FLAGS_RUN_EVEN_IF_DEVICE_NOT_INITIALIZED);
1866 
1867     //
1868     // Blacklisted devices return successfully in order to preserve the fabric state heartbeat
1869     // and ensure OOB utilities don't think the driver has died
1870     //
1871     if (device->device_blacklist_reason == NVSWITCH_DEVICE_BLACKLIST_REASON_MANUAL_OUT_OF_BAND)
1872     {
1873         NVSWITCH_PRINT(device, SETUP,
1874             "Blacklisted nvswitch at (%04x:%02x:%02x.%02x)\n",
1875             device->nvlink_device->pciInfo.domain,
1876             device->nvlink_device->pciInfo.bus,
1877             device->nvlink_device->pciInfo.device,
1878             device->nvlink_device->pciInfo.function);
1879         return NVL_SUCCESS;
1880     }
1881 
1882     if (is_blacklisted_by_os)
1883     {
1884         (void)nvswitch_lib_blacklist_device(device, NVSWITCH_DEVICE_BLACKLIST_REASON_MANUAL_IN_BAND);
1885         return NVL_SUCCESS;
1886     }
1887 
1888     for (link_num=0; link_num < nvswitch_get_num_links(device); link_num++)
1889     {
1890         if (!nvswitch_is_link_valid(device, link_num))
1891         {
1892             continue;
1893         }
1894 
1895         retval = nvswitch_create_link(device, link_num, &link);
1896         if (NVL_SUCCESS != retval)
1897         {
1898             NVSWITCH_PRINT(device, ERROR,
1899                 "Failed to create link %d : %d!\n",
1900                 link_num,
1901                 retval);
1902             goto nvswitch_link_fail;
1903         }
1904 
1905         retval = nvlink_lib_register_link(device->nvlink_device, link);
1906         if (NVL_SUCCESS != retval)
1907         {
1908             NVSWITCH_PRINT(device, ERROR,
1909                 "Failed to register link %d with the nvlink core : %d!\n",
1910                 link_num,
1911                 retval);
1912 
1913             // Free the single dangling link.
1914             nvswitch_destroy_link(link);
1915 
1916             goto nvswitch_link_fail;
1917         }
1918 
1919         nvswitch_reset_persistent_link_hw_state(device, link_num);
1920 
1921         //
1922         // During Nvswitch initialization, the default L1 thresholds are programmed by the
1923         // BIOS from the BIOS tables. Save these L1 Threshold Values in scratch registers
1924         // for use when resetting the thresholds to default.
1925         //
1926         nvswitch_program_l1_scratch_reg(device, link_num);
1927 
1928         //
1929         // WAR : Initializing the L1 threshold registers at this point as a WAR for
1930         // Bug 3963639 where it was discussed that the L1 threshold register should have
1931         // the default value for all available links and not just for active links.
1932         //
1933         nvswitch_init_lpwr_regs(link);
1934     }
1935 
1936     retval = nvswitch_set_training_mode(device);
1937 
1938     if (retval != NVL_SUCCESS)
1939     {
1940         NVSWITCH_PRINT(device, ERROR, "Failed to determine link training mode! rc: %d\n", retval);
1941         goto nvswitch_link_fail;
1942     }
1943     // Initialize select scratch registers to 0x0
1944     device->hal.nvswitch_init_scratch(device);
1945 
1946     retval = nvswitch_construct_error_log(&device->log_FATAL_ERRORS, 1024, NV_FALSE);
1947     if (retval != NVL_SUCCESS)
1948     {
1949         NVSWITCH_PRINT(device, ERROR, "Failed to construct log_FATAL_ERRORS! rc: %d\n", retval);
1950         goto nvswitch_construct_error_log_fail;
1951     }
1952 
1953     retval = nvswitch_construct_error_log(&device->log_NONFATAL_ERRORS, 1024, NV_TRUE);
1954     if (retval != NVL_SUCCESS)
1955     {
1956         NVSWITCH_PRINT(device, ERROR, "Failed to construct log_NONFATAL_ERRORS! rc: %d\n", retval);
1957         goto nvswitch_construct_error_log_fail;
1958     }
1959 
1960     retval = _nvswitch_construct_port_event_log(&device->log_PORT_EVENTS, NVSWITCH_PORT_EVENT_LOG_SIZE, NV_TRUE);
1961     if (retval != NVL_SUCCESS)
1962     {
1963         NVSWITCH_PRINT(device, ERROR, "Failed to construct log_PORT_EVENTS! rc: %d\n", retval);
1964         goto nvswitch_construct_port_event_log_fail;
1965     }
1966 
1967     if (device->regkeys.latency_counter == NV_SWITCH_REGKEY_LATENCY_COUNTER_LOGGING_ENABLE)
1968     {
1969         nvswitch_task_create(device, &nvswitch_internal_latency_bin_log,
1970             nvswitch_get_latency_sample_interval_msec(device) * NVSWITCH_INTERVAL_1MSEC_IN_NS * 9/10, 0);
1971     }
1972 
1973     nvswitch_task_create(device, &nvswitch_ecc_writeback_task,
1974         (60 * NVSWITCH_INTERVAL_1SEC_IN_NS), 0);
1975 
1976     if (IS_RTLSIM(device) || IS_EMULATION(device) || IS_FMODEL(device))
1977     {
1978         NVSWITCH_PRINT(device, WARN,
1979         "%s: Skipping setup of NvSwitch thermal alert monitoring\n",
1980             __FUNCTION__);
1981     }
1982     else
1983     {
1984         nvswitch_task_create(device, &nvswitch_monitor_thermal_alert,
1985             100*NVSWITCH_INTERVAL_1MSEC_IN_NS, 0);
1986     }
1987 
1988     device->nvlink_device->initialized = 1;
1989 
1990     return NVL_SUCCESS;
1991 
1992 nvswitch_construct_error_log_fail:
1993     //free allocated memory to avoid leaking
1994     nvswitch_destroy_error_log(device, &device->log_FATAL_ERRORS);
1995     nvswitch_destroy_error_log(device, &device->log_NONFATAL_ERRORS);
1996 
1997 nvswitch_construct_port_event_log_fail:
1998     //free allocated memory to avoid leaking
1999     _nvswitch_destroy_port_event_log(device, &device->log_PORT_EVENTS);
2000 
2001 nvswitch_link_fail:
2002     // Track down all links that successfully registered.
2003     for (link_num = 0; link_num < nvswitch_get_num_links(device); link_num++)
2004     {
2005         if (nvlink_lib_get_link(device->nvlink_device, link_num, &link) == NVL_SUCCESS)
2006         {
2007             nvlink_lib_unregister_link(link);
2008             nvswitch_destroy_link(link);
2009         }
2010     }
2011 
2012     nvswitch_destroy_inforom_objects(device);
2013 
2014 nvswitch_initialize_inforom_fail:
2015     nvswitch_destroy_inforom(device);
2016 
2017 nvswitch_initialize_device_state_fail:
2018     _nvswitch_destruct_cci(device);
2019 nvswitch_initialize_cci_fail:
2020     _nvswitch_destruct_soe(device);
2021     nvswitch_tasks_destroy(device);
2022 
2023     return retval;
2024 }
2025 
2026 NvBool
nvswitch_lib_validate_device_id(NvU32 device_id)2027 nvswitch_lib_validate_device_id
2028 (
2029     NvU32 device_id
2030 )
2031 {
2032     if (nvswitch_is_lr10_device_id(device_id))
2033     {
2034         return NV_TRUE;
2035     }
2036     if (nvswitch_is_ls10_device_id(device_id))
2037     {
2038         return NV_TRUE;
2039     }
2040     return NV_FALSE;
2041 }
2042 
2043 NvlStatus
nvswitch_lib_post_init_device(nvswitch_device * device)2044 nvswitch_lib_post_init_device
2045 (
2046     nvswitch_device *device
2047 )
2048 {
2049     NvlStatus retval;
2050     NvlStatus status;
2051     NvU32     link_num;
2052     NvU64     mode;
2053     nvlink_link *link;
2054     NvU64 enabledLinkMaskNonCci;
2055 
2056     if (!NVSWITCH_IS_DEVICE_INITIALIZED(device))
2057     {
2058         return -NVL_ERR_INVALID_STATE;
2059     }
2060 
2061     retval = _nvswitch_post_init_device_setup(device);
2062     if (retval != NVL_SUCCESS)
2063     {
2064         return retval;
2065     }
2066 
2067     if (nvswitch_is_bios_supported(device))
2068     {
2069         retval = nvswitch_bios_get_image(device);
2070         if (retval != NVL_SUCCESS)
2071         {
2072             return retval;
2073         }
2074 
2075         retval = nvswitch_parse_bios_image(device);
2076         if (retval != NVL_SUCCESS)
2077         {
2078             return retval;
2079         }
2080     }
2081     else
2082     {
2083         NVSWITCH_PRINT(device, ERROR,
2084             "%s: Skipping BIOS parsing since BIOS is unsupported.\n",
2085             __FUNCTION__);
2086     }
2087 
2088     if (nvswitch_is_cci_supported(device))
2089     {
2090         retval = cciLoad(device);
2091         if (NVL_SUCCESS != retval)
2092         {
2093             NVSWITCH_PRINT(device, ERROR, "%s: Init CCI failed\n",
2094                 __FUNCTION__);
2095             return retval;
2096         }
2097 
2098         enabledLinkMaskNonCci = nvswitch_get_enabled_link_mask(device);
2099 
2100         FOR_EACH_INDEX_IN_MASK(64, link_num, enabledLinkMaskNonCci)
2101         {
2102             if (cciIsLinkManaged(device, link_num))
2103             {
2104                 enabledLinkMaskNonCci = enabledLinkMaskNonCci & ~NVBIT64(link_num);
2105             }
2106         }
2107         FOR_EACH_INDEX_IN_MASK_END;
2108 
2109         if (enabledLinkMaskNonCci != 0)
2110         {
2111             nvswitch_task_create(device, &_nvswitch_update_link_state_led,
2112                                 NVSWITCH_INTERVAL_1SEC_IN_NS, 0);
2113         }
2114     }
2115     else
2116     {
2117         NVSWITCH_PRINT(device, INFO, "%s: Skipping CCI init.\n",
2118             __FUNCTION__);
2119     }
2120 
2121     retval = _nvswitch_setup_system_registers(device);
2122     if (retval != NVL_SUCCESS)
2123     {
2124         return retval;
2125     }
2126 
2127     nvswitch_smbpbi_post_init(device);
2128 
2129     // ALI launched by VBIOS on silicon
2130     if (IS_RTLSIM(device) || IS_EMULATION(device) || IS_FMODEL(device))
2131     {
2132         (void)nvswitch_launch_ALI(device);
2133     }
2134 
2135     //
2136     // There is an edge case where a hyperisor may not send same number
2137     // of reset to switch and GPUs, so try to re-train links in fault
2138     // if possible
2139     //
2140     for (link_num=0; link_num < nvswitch_get_num_links(device); link_num++)
2141     {
2142         // Sanity check
2143         if (!nvswitch_is_link_valid(device, link_num))
2144         {
2145             continue;
2146         }
2147 
2148         // CCI links are trained and managed by SOE, skip any driver based training
2149         if (cciIsLinkManaged(device, link_num))
2150         {
2151             continue;
2152         }
2153         status = nvlink_lib_get_link(device->nvlink_device, link_num, &link);
2154         if (status != NVL_SUCCESS)
2155         {
2156             NVSWITCH_PRINT(device, ERROR, "%s: Failed to get link for LinkId %d\n",
2157                         __FUNCTION__, link_num);
2158             continue;
2159         }
2160 
2161         // If the link is in fault then re-train
2162         if(_nvswitch_corelib_get_dl_link_mode(link, &mode) != NVL_SUCCESS)
2163         {
2164             NVSWITCH_PRINT(device, ERROR, "%s: nvlipt_lnk_status: Failed to check link mode! LinkId %d\n",
2165                         __FUNCTION__, link_num);
2166         }
2167         else if(mode == NVLINK_LINKSTATE_FAULT)
2168         {
2169             NVSWITCH_PRINT(device, INFO, "%s: retraining LinkId %d\n",
2170                         __FUNCTION__, link_num);
2171             nvswitch_reset_and_train_link(device, link);
2172         }
2173     }
2174 
2175     return NVL_SUCCESS;
2176 }
2177 
2178 void
nvswitch_lib_post_init_blacklist_device(nvswitch_device * device)2179 nvswitch_lib_post_init_blacklist_device
2180 (
2181     nvswitch_device *device
2182 )
2183 {
2184     _nvswitch_post_init_blacklist_device_setup(device);
2185 }
2186 
2187 void
_nvswitch_check_pending_data_and_notify(nvswitch_device * device,NVSWITCH_CLIENT_EVENT * event)2188 _nvswitch_check_pending_data_and_notify
2189 (
2190     nvswitch_device       *device,
2191     NVSWITCH_CLIENT_EVENT *event
2192 )
2193 {
2194     switch (event->eventId)
2195     {
2196         case NVSWITCH_DEVICE_EVENT_INBAND_DATA:
2197         {
2198             NvU32 i;
2199 
2200             for (i = 0; i < nvswitch_get_num_links(device); i++)
2201             {
2202                 if (!nvListIsEmpty(&device->link[i].inbandData.persistent_list) ||
2203                     !nvListIsEmpty(&device->link[i].inbandData.nonpersistent_list))
2204                 {
2205                     (void)nvswitch_os_notify_client_event(device->os_handle,
2206                                                           event->private_driver_data,
2207                                                           event->eventId);
2208                 }
2209             }
2210             break;
2211         }
2212 
2213         default:
2214             return;
2215     }
2216 }
2217 
2218 /*!
2219  * @brief: Gets the client event associated with the file descriptor
2220  *         if it already exists in the Device's client event list.
2221  *
2222  *         If found, and if there is pending data for the event,
2223  *         the event is triggered before returning to unblock the
2224  *         client right away.
2225  */
2226 NvlStatus
nvswitch_lib_get_client_event(nvswitch_device * device,void * osPrivate,NVSWITCH_CLIENT_EVENT ** ppClientEvent)2227 nvswitch_lib_get_client_event
2228 (
2229     nvswitch_device       *device,
2230     void                  *osPrivate,
2231     NVSWITCH_CLIENT_EVENT **ppClientEvent
2232 )
2233 {
2234     NVSWITCH_CLIENT_EVENT *curr = NULL;
2235 
2236     *ppClientEvent = NULL;
2237 
2238     if(!NVSWITCH_IS_DEVICE_VALID(device))
2239     {
2240         return -NVL_BAD_ARGS;
2241     }
2242 
2243     nvListForEachEntry(curr, &device->client_events_list, entry)
2244     {
2245         if (curr->private_driver_data == osPrivate)
2246         {
2247             *ppClientEvent = curr;
2248             _nvswitch_check_pending_data_and_notify(device, curr);
2249             return NVL_SUCCESS;
2250         }
2251     }
2252 
2253     return -NVL_NOT_FOUND;
2254 }
2255 
2256 /*!
2257  * @brief: Adds an event to the front of the
2258  *         Device's client event list.
2259  */
2260 NvlStatus
nvswitch_lib_add_client_event(nvswitch_device * device,void * osPrivate,NvU32 eventId)2261 nvswitch_lib_add_client_event
2262 (
2263     nvswitch_device *device,
2264     void            *osPrivate,
2265     NvU32           eventId
2266 )
2267 {
2268     NVSWITCH_CLIENT_EVENT *newEvent;
2269     NvlStatus status = NVL_SUCCESS;
2270 
2271     if (!NVSWITCH_IS_DEVICE_VALID(device))
2272     {
2273         return -NVL_BAD_ARGS;
2274     }
2275 
2276     if (eventId >= NVSWITCH_DEVICE_EVENT_COUNT)
2277     {
2278         NVSWITCH_PRINT(device, ERROR, "%s: Invalid event Id.\n", __FUNCTION__);
2279         return -NVL_BAD_ARGS;
2280     }
2281 
2282     // Invoke OS specific API to add event.
2283     status = nvswitch_os_add_client_event(device->os_handle,
2284                                           osPrivate,
2285                                           eventId);
2286     if (status != NVL_SUCCESS)
2287     {
2288         NVSWITCH_PRINT(device, ERROR, "%s: Failed to add client event.\n", __FUNCTION__);
2289         return status;
2290     }
2291 
2292     newEvent = nvswitch_os_malloc(sizeof(*newEvent));
2293     if (newEvent == NULL)
2294     {
2295         return -NVL_NO_MEM;
2296     }
2297 
2298     newEvent->eventId             = eventId;
2299     newEvent->private_driver_data = osPrivate;
2300 
2301     nvListAdd(&newEvent->entry, &device->client_events_list);
2302 
2303     return NVL_SUCCESS;
2304 }
2305 
2306 /*!
2307  * @brief: Removes all events corresponding to osPrivate,
2308  *         from the Device's client event list.
2309  */
2310 NvlStatus
nvswitch_lib_remove_client_events(nvswitch_device * device,void * osPrivate)2311 nvswitch_lib_remove_client_events
2312 (
2313     nvswitch_device *device,
2314     void            *osPrivate
2315 )
2316 {
2317     NVSWITCH_CLIENT_EVENT *curr = NULL;
2318     NVSWITCH_CLIENT_EVENT *next = NULL;
2319     NvlStatus status = NVL_SUCCESS;
2320 
2321     //
2322     // Device shutdown may happen before this is called, so return
2323     // if device is gone
2324     //
2325     if (!NVSWITCH_IS_DEVICE_VALID(device))
2326     {
2327         return NVL_SUCCESS;
2328     }
2329 
2330     nvListForEachEntry_safe(curr, next, &device->client_events_list, entry)
2331     {
2332         if (curr->private_driver_data == osPrivate)
2333         {
2334             nvListDel(&curr->entry);
2335             nvswitch_os_free(curr);
2336         }
2337     }
2338 
2339     // Invoke OS specific API to remove event.
2340     status = nvswitch_os_remove_client_event(device->os_handle,
2341                                              osPrivate);
2342     if (status != NVL_SUCCESS)
2343     {
2344         NVSWITCH_PRINT(device, ERROR, "%s: Failed to remove client events.\n", __FUNCTION__);
2345         return status;
2346     }
2347 
2348     return NVL_SUCCESS;
2349 }
2350 
2351 /*!
2352  * @brief: Notifies all events with matching event id in the
2353  *         Device's client event list.
2354  */
2355 NvlStatus
nvswitch_lib_notify_client_events(nvswitch_device * device,NvU32 eventId)2356 nvswitch_lib_notify_client_events
2357 (
2358     nvswitch_device *device,
2359     NvU32            eventId
2360 )
2361 {
2362     NvlStatus status;
2363     NVSWITCH_CLIENT_EVENT *curr = NULL;
2364 
2365     if (!NVSWITCH_IS_DEVICE_VALID(device))
2366     {
2367         return -NVL_BAD_ARGS;
2368     }
2369 
2370     if (eventId >= NVSWITCH_DEVICE_EVENT_COUNT)
2371     {
2372         NVSWITCH_PRINT(device, ERROR, "%s: Invalid event Id.\n", __FUNCTION__);
2373         return -NVL_BAD_ARGS;
2374     }
2375 
2376     nvListForEachEntry(curr, &device->client_events_list, entry)
2377     {
2378         if (curr->eventId == eventId)
2379         {
2380             // OS specific event notification.
2381             status = nvswitch_os_notify_client_event(device->os_handle,
2382                                                      curr->private_driver_data,
2383                                                      eventId);
2384             if (status != NVL_SUCCESS)
2385             {
2386                 return status;
2387             }
2388         }
2389     }
2390 
2391     return NVL_SUCCESS;
2392 }
2393 
2394 void
nvswitch_record_port_event(nvswitch_device * device,NVSWITCH_PORT_EVENT_LOG_TYPE * port_events,NvU32 link_id,NvU8 port_event_type)2395 nvswitch_record_port_event
2396 (
2397     nvswitch_device *device,
2398     NVSWITCH_PORT_EVENT_LOG_TYPE *port_events,
2399     NvU32 link_id,
2400     NvU8 port_event_type
2401 )
2402 {
2403     NvU32 idx;
2404 
2405     NVSWITCH_ASSERT(port_events != NULL);
2406 
2407     // If no port events log has been created, then don't log it.
2408     if ((port_events->port_event_log_size != 0) &&
2409         (port_events->port_event_log != NULL))
2410     {
2411         idx = (port_events->port_event_start + port_events->port_event_count)
2412                                         % port_events->port_event_log_size;
2413 
2414         if (port_events->port_event_count == port_events->port_event_log_size)
2415         {
2416             // Error: ring buffer is already full/
2417             if (port_events->overwritable)
2418             {
2419                 port_events->port_event_start = (port_events->port_event_start + 1)
2420                                                 % port_events->port_event_log_size;
2421                 port_events->bOverflow = NV_TRUE;
2422             }
2423             else
2424             {
2425                 // No logging, ring buffer is full
2426                 return;
2427             }
2428         }
2429         else
2430         {
2431             port_events->port_event_count++;
2432         }
2433         // Log port event info
2434         port_events->port_event_log[idx].link_id = link_id;
2435         port_events->port_event_log[idx].port_event_type = port_event_type;
2436 
2437         // Log tracking info
2438         port_events->port_event_log[idx].time = nvswitch_os_get_platform_time();
2439         port_events->port_event_log[idx].local_port_event_num = port_events->port_event_total;
2440     }
2441     port_events->port_event_total++;
2442 }
2443 
2444 /*
2445  * @Brief : Retrives a port event entry by index.
2446  *
2447  * @Description : Retrieves the port_event at index port_event_idx. If index is out
2448  *                of range, returns an empty port event entry with port_event_type = 2
2449  *
2450  * @param[in] device              NVSwitch device to contain this link
2451  * @param[in] port_events         Log of all port events with metadata
2452  * @param[in] port_event_idx      Index of entry to retrieve (0 = oldest port event)
2453  * @param[out] port_event_count  Clear only non-persistent list
2454  */
2455 void
nvswitch_get_port_event(nvswitch_device * device,NVSWITCH_PORT_EVENT_LOG_TYPE * port_events,NVSWITCH_PORT_EVENT_TYPE * port_event_entry,NvU32 port_event_idx,NvU32 * port_event_count)2456 nvswitch_get_port_event
2457 (
2458     nvswitch_device *device,
2459     NVSWITCH_PORT_EVENT_LOG_TYPE *port_events,
2460     NVSWITCH_PORT_EVENT_TYPE *port_event_entry,
2461     NvU32 port_event_idx,
2462     NvU32 *port_event_count
2463 )
2464 {
2465     NvU32 idx;
2466     NVSWITCH_ASSERT(port_events != NULL);
2467 
2468     if (port_event_entry != NULL)
2469     {
2470         // Index is out of range
2471         if (port_event_idx >= port_events->port_event_count)
2472         {
2473             nvswitch_os_memset(port_event_entry, 0, sizeof(*port_event_entry));
2474             port_event_entry->port_event_type = NVSWITCH_PORT_EVENT_TYPE_INVALID;
2475             port_event_entry->time = nvswitch_os_get_platform_time();
2476         }
2477         else
2478         {
2479             idx = (port_events->port_event_start + port_event_idx) % port_events->port_event_log_size;
2480             *port_event_entry = port_events->port_event_log[idx];
2481         }
2482     }
2483 
2484     if (port_event_count)
2485     {
2486         *port_event_count = port_events->port_event_count;
2487     }
2488 }
2489 
2490 NvlStatus
nvswitch_ctrl_get_port_events(nvswitch_device * device,NVSWITCH_GET_PORT_EVENTS_PARAMS * p)2491 nvswitch_ctrl_get_port_events
2492 (
2493     nvswitch_device *device,
2494     NVSWITCH_GET_PORT_EVENTS_PARAMS *p
2495 )
2496 {
2497     NvU32 index = 0;
2498     NvU32 count = 0;
2499     NVSWITCH_PORT_EVENT_LOG_TYPE *port_events = &device->log_PORT_EVENTS;
2500     NVSWITCH_PORT_EVENT_TYPE port_event;
2501 
2502     nvswitch_os_memset(p->portEvent, 0, sizeof(NVSWITCH_PORT_EVENT)
2503                                     *NVSWITCH_PORT_EVENT_COUNT_SIZE);
2504     p->nextPortEventIndex = port_events->port_event_total;
2505     p->portEventCount = 0;
2506     p->bOverflow = port_events->bOverflow;
2507 
2508     // Return if there are no more port events to get
2509     nvswitch_get_port_event(device, port_events, &port_event, index, &count);
2510     if (count == 0)
2511     {
2512         return NVL_SUCCESS;
2513     }
2514 
2515     // If port event's local_port_Event_num is smaller than the portEventIndex
2516     // passed in by the client, fast-forward index by the difference.
2517     // This will skip over port events that were previously read by the client.
2518     if (port_event.local_port_event_num < p->portEventIndex)
2519     {
2520         index = (NvU32) (p->portEventIndex - port_event.local_port_event_num);
2521     }
2522 
2523     // Return if there are no more events after fast-forwarding.
2524     if (index >= count)
2525     {
2526         return NVL_SUCCESS;
2527     }
2528 
2529     while ((p->portEventCount < NVSWITCH_PORT_EVENT_COUNT_SIZE) && (index < count))
2530     {
2531         nvswitch_get_port_event(device, port_events, &port_event, index, NULL);
2532 
2533         p->portEvent[p->portEventCount].port_event_type = port_event.port_event_type;
2534         p->portEvent[p->portEventCount].link_id = port_event.link_id;
2535         p->portEvent[p->portEventCount].time = port_event.time;
2536 
2537         p->portEventCount++;
2538         index++;
2539     }
2540 
2541     p->portEventIndex = port_event.local_port_event_num + 1;
2542 
2543     return NVL_SUCCESS;
2544 }
2545 
2546 /*!
2547    @brief: Release ROM image from memory.
2548 */
2549 void
_nvswitch_destroy_rom(nvswitch_device * device)2550 _nvswitch_destroy_rom(nvswitch_device *device)
2551 {
2552     if (device->biosImage.pImage != NULL)
2553     {
2554         nvswitch_os_free(device->biosImage.pImage);
2555         device->biosImage.pImage = NULL;
2556     }
2557 }
2558 
2559 /*!
2560  * @brief: Free the device's client event list
2561  */
2562 static void
_nvswitch_destroy_event_list(nvswitch_device * device)2563 _nvswitch_destroy_event_list(nvswitch_device *device)
2564 {
2565     NVSWITCH_CLIENT_EVENT *curr = NULL;
2566     NVSWITCH_CLIENT_EVENT *next = NULL;
2567 
2568     nvListForEachEntry_safe(curr, next, &device->client_events_list, entry)
2569     {
2570         nvListDel(&curr->entry);
2571         nvswitch_os_free(curr);
2572     }
2573 }
2574 
2575 NvlStatus
nvswitch_lib_shutdown_device(nvswitch_device * device)2576 nvswitch_lib_shutdown_device
2577 (
2578     nvswitch_device *device
2579 )
2580 {
2581     NVSWITCH_INBAND_FLUSH_DATA_PARAMS p;
2582 
2583     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
2584     {
2585         return -NVL_BAD_ARGS;
2586     }
2587 
2588     //
2589     // Set fabric state to offline
2590     //
2591     if (device->device_fabric_state != NVSWITCH_DEVICE_FABRIC_STATE_BLACKLISTED)
2592         device->device_fabric_state = NVSWITCH_DEVICE_FABRIC_STATE_OFFLINE;
2593     device->driver_fabric_state = NVSWITCH_DRIVER_FABRIC_STATE_OFFLINE;
2594     (void)device->hal.nvswitch_write_fabric_state(device);
2595 
2596     nvswitch_hw_counter_shutdown(device);
2597 
2598     // FLUSH any pending messages to avoid memory leaks
2599     p.linkMask = nvswitch_get_enabled_link_mask(device);
2600     _nvswitch_ctrl_inband_flush_data(device, &p);
2601 
2602     _nvswitch_destruct_cci(device);
2603     _nvswitch_led_shutdown(device);
2604 
2605     _nvswitch_unregister_links(device);
2606 
2607     nvswitch_destroy_error_log(device, &device->log_FATAL_ERRORS);
2608     nvswitch_destroy_error_log(device, &device->log_NONFATAL_ERRORS);
2609 
2610     _nvswitch_destroy_port_event_log(device, &device->log_PORT_EVENTS);
2611 
2612     nvswitch_smbpbi_unload(device);
2613     _nvswitch_destroy_event_list(device);
2614 
2615     nvswitch_destroy_inforom_objects(device);
2616     nvswitch_destroy_inforom(device);
2617 
2618     nvswitch_smbpbi_destroy(device);
2619 
2620     nvswitch_destroy_device_state(device);
2621 
2622     _nvswitch_destroy_rom(device);
2623 
2624     _nvswitch_destruct_soe(device);
2625 
2626     nvswitch_tasks_destroy(device);
2627 
2628     return NVL_SUCCESS;
2629 }
2630 
2631 NvlStatus
nvswitch_lib_get_log_count(nvswitch_device * device,NvU32 * fatal,NvU32 * nonfatal,NvU32 * portEvent)2632 nvswitch_lib_get_log_count
2633 (
2634     nvswitch_device *device,
2635     NvU32 *fatal, NvU32 *nonfatal, NvU32 *portEvent
2636 )
2637 {
2638     if (!NVSWITCH_IS_DEVICE_INITIALIZED(device) ||
2639         fatal == NULL || nonfatal == NULL || portEvent == NULL)
2640     {
2641         return -NVL_BAD_ARGS;
2642     }
2643 
2644     *fatal = device->log_FATAL_ERRORS.error_count;
2645     *nonfatal = device->log_NONFATAL_ERRORS.error_count;
2646     *portEvent = device->log_PORT_EVENTS.port_event_count;
2647     // No report of log_INFO currently
2648 
2649     return NVL_SUCCESS;
2650 }
2651 
2652 NvlStatus
nvswitch_lib_load_platform_info(nvswitch_device * device)2653 nvswitch_lib_load_platform_info
2654 (
2655     nvswitch_device *device
2656 )
2657 {
2658     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
2659     {
2660         return -NVL_BAD_ARGS;
2661     }
2662 
2663     device->hal.nvswitch_determine_platform(device);
2664 
2665     return NVL_SUCCESS;
2666 }
2667 
2668 void
nvswitch_lib_get_device_info(nvswitch_device * device,struct nvlink_pci_info ** pciInfo)2669 nvswitch_lib_get_device_info
2670 (
2671     nvswitch_device *device,
2672     struct nvlink_pci_info **pciInfo
2673 )
2674 {
2675     if (!NVSWITCH_IS_DEVICE_VALID(device) || pciInfo == NULL)
2676     {
2677         NVSWITCH_ASSERT(0);
2678         return;
2679     }
2680 
2681     *pciInfo = &device->nvlink_device->pciInfo;
2682 }
2683 
2684 NvlStatus
nvswitch_lib_get_bios_version(nvswitch_device * device,NvU64 * version)2685 nvswitch_lib_get_bios_version
2686 (
2687     nvswitch_device *device,
2688     NvU64 *version
2689 )
2690 {
2691     NVSWITCH_GET_BIOS_INFO_PARAMS p = { 0 };
2692     NvlStatus ret;
2693 
2694     if (!device)
2695         return -NVL_BAD_ARGS;
2696 
2697     ret = device->hal.nvswitch_ctrl_get_bios_info(device, &p);
2698 
2699     if (version != NULL)
2700     {
2701     *version = p.version;
2702     }
2703 
2704     return ret;
2705 }
2706 
2707 NvlStatus
nvswitch_lib_use_pin_irq(nvswitch_device * device)2708 nvswitch_lib_use_pin_irq
2709 (
2710      nvswitch_device *device
2711 )
2712 {
2713     return IS_FMODEL(device);
2714 }
2715 
2716 
2717 NvlStatus
nvswitch_lib_register_device(NvU16 pci_domain,NvU8 pci_bus,NvU8 pci_device,NvU8 pci_func,NvU16 pci_device_id,void * os_handle,NvU32 os_instance,nvswitch_device ** return_device)2718 nvswitch_lib_register_device
2719 (
2720     NvU16 pci_domain,
2721     NvU8 pci_bus,
2722     NvU8 pci_device,
2723     NvU8 pci_func,
2724     NvU16 pci_device_id,
2725     void *os_handle,
2726     NvU32 os_instance,
2727     nvswitch_device **return_device
2728 )
2729 {
2730     nvswitch_device *device  = NULL;
2731     nvlink_device   *coreDev = NULL;
2732     NvlStatus        retval  = NVL_SUCCESS;
2733 
2734     if (!nvlink_lib_is_initialized())
2735     {
2736         NVSWITCH_PRINT(device, ERROR,
2737             "NVLink core lib isn't initialized yet!\n");
2738         return -NVL_INITIALIZATION_TOTAL_FAILURE;
2739     }
2740 
2741     if (return_device == NULL || os_handle == NULL)
2742     {
2743         return -NVL_BAD_ARGS;
2744     }
2745 
2746     *return_device = NULL;
2747 
2748     device = nvswitch_os_malloc(sizeof(*device));
2749     if (NULL == device)
2750     {
2751         NVSWITCH_PRINT(device, ERROR,
2752             "nvswitch_os_malloc during device creation failed!\n");
2753         return -NVL_NO_MEM;
2754     }
2755     nvswitch_os_memset(device, 0, sizeof(*device));
2756 
2757     nvswitch_os_snprintf(device->name, sizeof(device->name),
2758          NVSWITCH_DEVICE_NAME "%d", os_instance);
2759 
2760     coreDev = nvswitch_os_malloc(sizeof(*coreDev));
2761     if (NULL == coreDev)
2762     {
2763         NVSWITCH_PRINT(device, ERROR,
2764             "nvswitch_os_malloc during device creation failed!\n");
2765 
2766         retval = -NVL_NO_MEM;
2767         goto nvlink_lib_register_device_fail;
2768     }
2769     nvswitch_os_memset(coreDev, 0, sizeof(*coreDev));
2770 
2771     coreDev->driverName =
2772         nvswitch_os_malloc(sizeof(NVSWITCH_DRIVER_NAME));
2773     if (coreDev->driverName == NULL)
2774     {
2775         NVSWITCH_PRINT(device, ERROR,
2776             "nvswitch_os_malloc during device creation failed!\n");
2777 
2778         retval = -NVL_NO_MEM;
2779         goto nvlink_lib_register_device_fail;
2780     }
2781     nvswitch_os_memcpy(coreDev->driverName, NVSWITCH_DRIVER_NAME,
2782                        sizeof(NVSWITCH_DRIVER_NAME));
2783 
2784     device->os_handle   = os_handle;
2785     device->os_instance = os_instance;
2786 
2787     device->nvlink_device             = coreDev;
2788     device->nvlink_device->deviceName = device->name;
2789     device->nvlink_device->uuid = NULL; // No UUID support for switch
2790 
2791     device->nvlink_device->pciInfo.domain      = pci_domain;
2792     device->nvlink_device->pciInfo.bus         = pci_bus;
2793     device->nvlink_device->pciInfo.device      = pci_device;
2794     device->nvlink_device->pciInfo.function    = pci_func;
2795     device->nvlink_device->pciInfo.pciDeviceId = pci_device_id;
2796 
2797     // nvlink_device has a back pointer to nvswitch_device
2798     device->nvlink_device->pDevInfo = device;
2799     device->nvlink_device->type = NVLINK_DEVICE_TYPE_NVSWITCH;
2800 
2801     //
2802     // Initialize the Fabric State
2803     //
2804     device->fm_timeout = NVSWITCH_DEFAULT_FM_HEARTBEAT_TIMEOUT_MSEC;
2805     device->fabric_state_sequence_number = 0;
2806     device->driver_fabric_state = NVSWITCH_DRIVER_FABRIC_STATE_STANDBY;
2807     device->device_fabric_state = NVSWITCH_DEVICE_FABRIC_STATE_STANDBY;
2808     device->device_blacklist_reason = NVSWITCH_DEVICE_BLACKLIST_REASON_NONE;
2809 
2810     //
2811     // Initialize TNVL Mode
2812     //
2813     device->tnvl_mode = NVSWITCH_DEVICE_TNVL_MODE_DISABLED;
2814 
2815     //
2816     // Initialize HAL connectivity as early as possible so that other lib
2817     // interfaces can work.
2818     //
2819     retval = _nvswitch_setup_hal(device, device->nvlink_device->pciInfo.pciDeviceId);
2820     if (retval != NVL_SUCCESS)
2821     {
2822         goto nvlink_lib_register_device_fail;
2823     }
2824 
2825     //
2826     // Initialize regkeys as early as possible so that most routines can take
2827     // advantage of them.
2828     //
2829     _nvswitch_init_device_regkeys(device);
2830 
2831     // After regkeys have been set then only set the enableALI field.
2832     device->nvlink_device->enableALI = (device->regkeys.link_training_mode ==
2833                         NV_SWITCH_REGKEY_LINK_TRAINING_SELECT_ALI) ? NV_TRUE:NV_FALSE;
2834 
2835     retval = nvlink_lib_register_device(device->nvlink_device);
2836     if (NVL_SUCCESS != retval)
2837     {
2838         NVSWITCH_PRINT(device, ERROR,
2839             "nvlinklib register device failed!\n");
2840         goto nvlink_lib_register_device_fail;
2841     }
2842 
2843     *return_device = device;
2844 
2845     NVSWITCH_PRINT(device, SETUP,
2846         "Successfully registered with nvlinkcore\n");
2847 
2848     return retval;
2849 
2850 nvlink_lib_register_device_fail:
2851 
2852     if (NULL != coreDev)
2853     {
2854         nvswitch_os_free(coreDev->driverName);
2855         nvswitch_os_free(coreDev);
2856     }
2857 
2858     if (NULL != device)
2859         nvswitch_os_free(device);
2860 
2861     return retval;
2862 }
2863 
2864 void
nvswitch_lib_unregister_device(nvswitch_device * device)2865 nvswitch_lib_unregister_device
2866 (
2867     nvswitch_device *device
2868 )
2869 {
2870     if (!NVSWITCH_IS_DEVICE_VALID(device))
2871     {
2872         NVSWITCH_ASSERT(0);
2873         return;
2874     }
2875 
2876     nvlink_lib_unregister_device(device->nvlink_device);
2877 
2878     nvswitch_os_free(device->nvlink_device->driverName);
2879     nvswitch_os_free(device->nvlink_device);
2880     nvswitch_os_free(device);
2881 
2882     return;
2883 }
2884 
2885 /*!
2886  * @brief: Gets the mask of valid I2C ports on the
2887  *         Device.
2888  */
2889 NvlStatus
nvswitch_lib_get_valid_ports_mask(nvswitch_device * device,NvU32 * validPortsMask)2890 nvswitch_lib_get_valid_ports_mask
2891 (
2892     nvswitch_device *device,
2893     NvU32 *validPortsMask
2894 )
2895 {
2896     NvU32 port_info;
2897     NvU32 i;
2898     NvU32 ports_mask = 0;
2899     NvBool is_i2c_access_allowed;
2900     NvBool is_port_allowed;
2901 
2902     if (!NVSWITCH_IS_DEVICE_VALID(device) ||
2903         (validPortsMask == NULL))
2904     {
2905         return -NVL_BAD_ARGS;
2906     }
2907 
2908     is_i2c_access_allowed = (device->regkeys.i2c_access_control ==
2909                              NV_SWITCH_REGKEY_I2C_ACCESS_CONTROL_ENABLE) ?
2910                                 NV_TRUE : NV_FALSE;
2911 
2912     for (i = 0; i < NVSWITCH_MAX_I2C_PORTS; i++)
2913     {
2914         port_info = nvswitch_i2c_get_port_info(device, i);
2915 
2916         is_port_allowed = is_i2c_access_allowed ? NV_TRUE :
2917                               FLD_TEST_DRF(_I2C, _PORTINFO, _ACCESS_ALLOWED, _TRUE,
2918                                            port_info);
2919 
2920         if (is_port_allowed &&
2921             FLD_TEST_DRF(_I2C, _PORTINFO, _DEFINED, _PRESENT, port_info))
2922         {
2923             ports_mask |= NVBIT(i);
2924         }
2925     }
2926 
2927     *validPortsMask = ports_mask;
2928     return NVL_SUCCESS;
2929 }
2930 
2931 /*!
2932  * @brief: Returns if the I2C transactions are supported.
2933  */
2934 NvBool
nvswitch_lib_is_i2c_supported(nvswitch_device * device)2935 nvswitch_lib_is_i2c_supported
2936 (
2937     nvswitch_device *device
2938 )
2939 {
2940     if (!NVSWITCH_IS_DEVICE_VALID(device))
2941     {
2942         NVSWITCH_ASSERT(0);
2943         return NV_FALSE;
2944     }
2945 
2946     return nvswitch_is_i2c_supported(device);
2947 }
2948 
2949 static NvlStatus
_nvswitch_perform_i2c_transfer(nvswitch_device * device,NvU32 client,NvU8 type,NvU16 addr,NvU8 port,NvU8 cmd,NvU32 msgLength,NvU8 * pData)2950 _nvswitch_perform_i2c_transfer
2951 (
2952     nvswitch_device *device,
2953     NvU32 client,
2954     NvU8 type,
2955     NvU16 addr,
2956     NvU8 port,
2957     NvU8 cmd,
2958     NvU32 msgLength,
2959     NvU8 *pData
2960 )
2961 {
2962     NvlStatus status;
2963     NvU16 deviceAddr;
2964     NvU32 speedMode;
2965     NvBool bIsRead = NV_FALSE;
2966     NvU32 flags = 0;
2967     NVSWITCH_CTRL_I2C_INDEXED_PARAMS i2c_params = {0};
2968     NvBool is_i2c_access_allowed;
2969 
2970     if (!nvswitch_os_is_admin())
2971     {
2972         return -NVL_ERR_INSUFFICIENT_PERMISSIONS;
2973     }
2974 
2975     is_i2c_access_allowed = (device->regkeys.i2c_access_control ==
2976                              NV_SWITCH_REGKEY_I2C_ACCESS_CONTROL_ENABLE) ?
2977                                 NV_TRUE : NV_FALSE;
2978 
2979     //
2980     // The address needs to be shifted by 1,
2981     // See NVSWITCH_CTRL_I2C_INDEXED_PARAMS
2982     //
2983     deviceAddr = addr << 1;
2984     speedMode  = device->pI2c->Ports[port].defaultSpeedMode;
2985     flags      = DRF_DEF(SWITCH_CTRL, _I2C_FLAGS, _START, _SEND)              |
2986                  DRF_DEF(SWITCH_CTRL, _I2C_FLAGS, _STOP, _SEND)               |
2987                  DRF_DEF(SWITCH_CTRL, _I2C_FLAGS, _ADDRESS_MODE, _7BIT)       |
2988                  DRF_DEF(SWITCH_CTRL, _I2C_FLAGS, _FLAVOR, _HW)               |
2989                  DRF_DEF(SWITCH_CTRL, _I2C_FLAGS, _BLOCK_PROTOCOL, _DISABLED) |
2990                  DRF_DEF(SWITCH_CTRL, _I2C_FLAGS, _TRANSACTION_MODE, _NORMAL);
2991 
2992     switch (speedMode)
2993     {
2994         case NVSWITCH_I2C_SPEED_MODE_1000KHZ:
2995         {
2996             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _SPEED_MODE, _1000KHZ, flags);
2997             break;
2998         }
2999         case NVSWITCH_I2C_SPEED_MODE_400KHZ:
3000         {
3001             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _SPEED_MODE, _400KHZ, flags);
3002             break;
3003         }
3004         case NVSWITCH_I2C_SPEED_MODE_300KHZ:
3005         {
3006             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _SPEED_MODE, _300KHZ, flags);
3007             break;
3008         }
3009         case NVSWITCH_I2C_SPEED_MODE_200KHZ:
3010         {
3011             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _SPEED_MODE, _200KHZ, flags);
3012             break;
3013         }
3014         case NVSWITCH_I2C_SPEED_MODE_100KHZ:
3015         {
3016             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _SPEED_MODE, _100KHZ, flags);
3017             break;
3018         }
3019         default:
3020         {
3021             NVSWITCH_PRINT(device, ERROR, "Invalid I2C speed!\n");
3022             status = -NVL_BAD_ARGS;
3023             goto end;
3024         }
3025     }
3026 
3027     switch (type)
3028     {
3029         case NVSWITCH_I2C_CMD_READ:
3030             bIsRead = NV_TRUE;
3031             // Fall through
3032         case NVSWITCH_I2C_CMD_WRITE:
3033         {
3034             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _INDEX_LENGTH, _ZERO, flags);
3035             break;
3036         }
3037         case NVSWITCH_I2C_CMD_SMBUS_READ:
3038         {
3039             bIsRead = NV_TRUE;
3040             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _RESTART, _SEND, flags);
3041             // Fall through
3042         }
3043         case NVSWITCH_I2C_CMD_SMBUS_WRITE:
3044         {
3045             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _INDEX_LENGTH, _ONE, flags);
3046             break;
3047         }
3048         case NVSWITCH_I2C_CMD_SMBUS_QUICK_READ:
3049             bIsRead = NV_TRUE;
3050             // Fall through
3051         case NVSWITCH_I2C_CMD_SMBUS_QUICK_WRITE:
3052         {
3053             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _INDEX_LENGTH, _ZERO, flags);
3054             msgLength = 0;
3055             break;
3056         }
3057         default:
3058         {
3059             NVSWITCH_PRINT(device, ERROR, "Invalid SMBUS protocol! Protocol not supported.\n");
3060             status = -NVL_BAD_ARGS;
3061             goto end;
3062         }
3063     }
3064 
3065     if (!is_i2c_access_allowed &&
3066         !nvswitch_i2c_is_device_access_allowed(device, port, deviceAddr, bIsRead))
3067     {
3068         return -NVL_BAD_ARGS;
3069     }
3070 
3071     if (msgLength > NVSWITCH_CTRL_I2C_MESSAGE_LENGTH_MAX)
3072     {
3073         NVSWITCH_PRINT(device, ERROR,
3074             "Length of buffer (0x%x bytes) provided larger than max (0x%x bytes)\n",
3075              msgLength, NVSWITCH_CTRL_I2C_MESSAGE_LENGTH_MAX);
3076         status = -NVL_BAD_ARGS;
3077         goto end;
3078     }
3079 
3080     if (bIsRead)
3081     {
3082         i2c_params.bIsRead = NV_TRUE;
3083     }
3084     else
3085     {
3086         flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _RESTART, _NONE, flags);
3087         nvswitch_os_memcpy(i2c_params.message, pData, msgLength);
3088     }
3089 
3090     if (FLD_TEST_DRF(SWITCH_CTRL, _I2C_FLAGS, _INDEX_LENGTH, _ONE, flags))
3091     {
3092         i2c_params.index[0] = cmd;
3093     }
3094 
3095     i2c_params.port     = port;
3096     i2c_params.address  = deviceAddr;
3097     i2c_params.acquirer = client;
3098     i2c_params.flags    = flags;
3099     i2c_params.messageLength = msgLength;
3100 
3101     status = nvswitch_ctrl_i2c_indexed(device, &i2c_params);
3102     if (status != NVL_SUCCESS)
3103     {
3104         NVSWITCH_PRINT(device, ERROR, "I2C transfer Failed!\n");
3105         goto end;
3106     }
3107 
3108     if (bIsRead)
3109     {
3110         nvswitch_os_memcpy(pData, i2c_params.message, msgLength);
3111     }
3112 
3113 end:
3114     return status;
3115 }
3116 
3117 /*!
3118  * @brief: Performs an I2C transaction.
3119  */
3120 NvlStatus
nvswitch_lib_i2c_transfer(nvswitch_device * device,NvU32 port,NvU8 type,NvU8 addr,NvU8 command,NvU32 len,NvU8 * pData)3121 nvswitch_lib_i2c_transfer
3122 (
3123     nvswitch_device *device,
3124     NvU32 port,
3125     NvU8 type,
3126     NvU8 addr,
3127     NvU8 command,
3128     NvU32 len,
3129     NvU8 *pData
3130 )
3131 {
3132     NvlStatus status;
3133     NvU32 port_info;
3134     NvBool is_i2c_access_allowed;
3135     NvBool is_port_allowed;
3136 
3137     if (!NVSWITCH_IS_DEVICE_VALID(device))
3138     {
3139         NVSWITCH_ASSERT(0);
3140         return -NVL_ERR_INVALID_STATE;
3141     }
3142 
3143     port_info = nvswitch_i2c_get_port_info(device, port);
3144 
3145     is_i2c_access_allowed = (device->regkeys.i2c_access_control ==
3146                              NV_SWITCH_REGKEY_I2C_ACCESS_CONTROL_ENABLE) ?
3147                                 NV_TRUE : NV_FALSE;
3148     is_port_allowed = is_i2c_access_allowed ? NV_TRUE :
3149                           FLD_TEST_DRF(_I2C, _PORTINFO, _ACCESS_ALLOWED, _TRUE,
3150                                        port_info);
3151 
3152     if (!is_port_allowed ||
3153         !FLD_TEST_DRF(_I2C, _PORTINFO, _DEFINED, _PRESENT, port_info))
3154     {
3155         NVSWITCH_PRINT(device, INFO,
3156             "%s: Invalid port access %d.\n",
3157             __FUNCTION__, port);
3158         return (-NVL_BAD_ARGS);
3159     }
3160 
3161     status = _nvswitch_perform_i2c_transfer(device, NVSWITCH_I2C_ACQUIRER_EXTERNAL,
3162                                             type, (NvU16)addr, port, command, len, pData);
3163     if (status != NVL_SUCCESS)
3164     {
3165         NVSWITCH_PRINT(device, ERROR, "I2C transaction failed!\n");
3166         return status;
3167     }
3168 
3169     return NVL_SUCCESS;
3170 }
3171 
3172 void
nvswitch_timeout_create(NvU64 timeout_ns,NVSWITCH_TIMEOUT * time)3173 nvswitch_timeout_create
3174 (
3175     NvU64   timeout_ns,
3176     NVSWITCH_TIMEOUT *time
3177 )
3178 {
3179     NvU64   time_current;
3180 
3181     time_current = nvswitch_os_get_platform_time();
3182     time->timeout_ns = time_current + timeout_ns;
3183 }
3184 
3185 NvBool
nvswitch_timeout_check(NVSWITCH_TIMEOUT * time)3186 nvswitch_timeout_check
3187 (
3188     NVSWITCH_TIMEOUT *time
3189 )
3190 {
3191     NvU64   time_current;
3192 
3193     time_current = nvswitch_os_get_platform_time();
3194     return (time->timeout_ns <= time_current);
3195 }
3196 
3197 NvlStatus
nvswitch_task_create(nvswitch_device * device,void (* task_fn)(nvswitch_device * device),NvU64 period_nsec,NvU32 flags)3198 nvswitch_task_create
3199 (
3200     nvswitch_device *device,
3201     void (*task_fn)(nvswitch_device *device),
3202     NvU64 period_nsec,
3203     NvU32 flags
3204 )
3205 {
3206     NVSWITCH_TASK_TYPE *task;
3207     task = nvswitch_os_malloc(sizeof(NVSWITCH_TASK_TYPE));
3208 
3209     if (task == NULL)
3210     {
3211         NVSWITCH_PRINT(device, ERROR,
3212             "%s: Unable to allocate task.\n",
3213             __FUNCTION__);
3214         return -NVL_NO_MEM;
3215     }
3216     else
3217     {
3218         task->task_fn_devptr = task_fn;
3219         task->task_args = NULL;
3220         task->period_nsec = period_nsec;
3221         task->last_run_nsec = nvswitch_os_get_platform_time(); // Prevent deferred tasks from being run immediately
3222         task->flags = flags;
3223         task->prev = NULL;
3224         task->next = device->tasks;
3225         if (device->tasks != NULL)
3226         {
3227             device->tasks->prev = task;
3228         }
3229         device->tasks = task;
3230     }
3231 
3232     return NVL_SUCCESS;
3233 }
3234 
3235 NvlStatus
nvswitch_task_create_args(nvswitch_device * device,void * fn_args,void (* task_fn)(nvswitch_device * device,void * fn_args),NvU64 period_nsec,NvU32 flags)3236 nvswitch_task_create_args
3237 (
3238     nvswitch_device *device,
3239     void *fn_args,
3240     void (*task_fn)(nvswitch_device* device, void *fn_args),
3241     NvU64 period_nsec,
3242     NvU32 flags
3243 )
3244 {
3245     NVSWITCH_TASK_TYPE *task;
3246     task = nvswitch_os_malloc(sizeof(NVSWITCH_TASK_TYPE));
3247 
3248     flags = flags | NVSWITCH_TASK_TYPE_FLAGS_VOID_PTR_ARGS;  // ensure dispatcher always executes tasks passed through this function with args
3249 
3250     if (task == NULL)
3251     {
3252         NVSWITCH_PRINT(device, ERROR,
3253             "%s: Unable to allocate task.\n",
3254             __FUNCTION__);
3255         return -NVL_NO_MEM;
3256     }
3257     else
3258     {
3259         task->task_fn_vdptr = task_fn;
3260         task->task_args = fn_args;
3261         task->period_nsec = period_nsec;
3262         task->last_run_nsec = nvswitch_os_get_platform_time(); // Prevent deferred tasks from being run immediately
3263         task->flags = flags;
3264         task->prev = NULL;
3265         task->next = device->tasks;
3266         if (device->tasks != NULL)
3267         {
3268             device->tasks->prev = task;
3269         }
3270         device->tasks = task;
3271     }
3272 
3273     return NVL_SUCCESS;
3274 }
3275 
3276 void
nvswitch_tasks_destroy(nvswitch_device * device)3277 nvswitch_tasks_destroy
3278 (
3279     nvswitch_device *device
3280 )
3281 {
3282     NVSWITCH_TASK_TYPE *task = device->tasks;
3283     NVSWITCH_TASK_TYPE *next_task;
3284 
3285     device->tasks = NULL;
3286 
3287     while (task)
3288     {
3289         next_task = task->next;
3290         nvswitch_os_free(task);
3291         task = next_task;
3292     }
3293 }
3294 
3295 void
nvswitch_destroy_device_state(nvswitch_device * device)3296 nvswitch_destroy_device_state
3297 (
3298     nvswitch_device *device
3299 )
3300 {
3301     device->hal.nvswitch_destroy_device_state(device);
3302 }
3303 
3304 static NvlStatus
_nvswitch_ctrl_get_info(nvswitch_device * device,NVSWITCH_GET_INFO * p)3305 _nvswitch_ctrl_get_info
3306 (
3307     nvswitch_device *device,
3308     NVSWITCH_GET_INFO *p
3309 )
3310 {
3311     return device->hal.nvswitch_ctrl_get_info(device, p);
3312 }
3313 
3314 static NvlStatus
_nvswitch_ctrl_get_nvlink_status(nvswitch_device * device,NVSWITCH_GET_NVLINK_STATUS_PARAMS * ret)3315 _nvswitch_ctrl_get_nvlink_status
3316 (
3317     nvswitch_device *device,
3318     NVSWITCH_GET_NVLINK_STATUS_PARAMS *ret
3319 )
3320 {
3321     return device->hal.nvswitch_ctrl_get_nvlink_status(device, ret);
3322 }
3323 
3324 static NvlStatus
_nvswitch_ctrl_get_counters(nvswitch_device * device,NVSWITCH_NVLINK_GET_COUNTERS_PARAMS * ret)3325 _nvswitch_ctrl_get_counters
3326 (
3327     nvswitch_device *device,
3328     NVSWITCH_NVLINK_GET_COUNTERS_PARAMS *ret
3329 )
3330 {
3331     return device->hal.nvswitch_ctrl_get_counters(device, ret);
3332 }
3333 
3334 NvlStatus
nvswitch_set_nport_port_config(nvswitch_device * device,NVSWITCH_SET_SWITCH_PORT_CONFIG * p)3335 nvswitch_set_nport_port_config
3336 (
3337     nvswitch_device *device,
3338     NVSWITCH_SET_SWITCH_PORT_CONFIG *p
3339 )
3340 {
3341     return device->hal.nvswitch_set_nport_port_config(device, p);
3342 }
3343 
3344 static NvlStatus
_nvswitch_ctrl_set_switch_port_config(nvswitch_device * device,NVSWITCH_SET_SWITCH_PORT_CONFIG * p)3345 _nvswitch_ctrl_set_switch_port_config
3346 (
3347     nvswitch_device *device,
3348     NVSWITCH_SET_SWITCH_PORT_CONFIG *p
3349 )
3350 {
3351     return device->hal.nvswitch_ctrl_set_switch_port_config(device, p);
3352 }
3353 
3354 static NvlStatus
_nvswitch_ctrl_get_ingress_request_table(nvswitch_device * device,NVSWITCH_GET_INGRESS_REQUEST_TABLE_PARAMS * params)3355 _nvswitch_ctrl_get_ingress_request_table
3356 (
3357     nvswitch_device *device,
3358     NVSWITCH_GET_INGRESS_REQUEST_TABLE_PARAMS *params
3359 )
3360 {
3361     return device->hal.nvswitch_ctrl_get_ingress_request_table(device, params);
3362 }
3363 
3364 static NvlStatus
_nvswitch_ctrl_set_ingress_request_table(nvswitch_device * device,NVSWITCH_SET_INGRESS_REQUEST_TABLE * p)3365 _nvswitch_ctrl_set_ingress_request_table
3366 (
3367     nvswitch_device *device,
3368     NVSWITCH_SET_INGRESS_REQUEST_TABLE *p
3369 )
3370 {
3371     return device->hal.nvswitch_ctrl_set_ingress_request_table(device, p);
3372 }
3373 
3374 static NvlStatus
_nvswitch_ctrl_set_ingress_request_valid(nvswitch_device * device,NVSWITCH_SET_INGRESS_REQUEST_VALID * p)3375 _nvswitch_ctrl_set_ingress_request_valid
3376 (
3377     nvswitch_device *device,
3378     NVSWITCH_SET_INGRESS_REQUEST_VALID *p
3379 )
3380 {
3381     return device->hal.nvswitch_ctrl_set_ingress_request_valid(device, p);
3382 }
3383 
3384 static NvlStatus
_nvswitch_ctrl_get_ingress_response_table(nvswitch_device * device,NVSWITCH_GET_INGRESS_RESPONSE_TABLE_PARAMS * params)3385 _nvswitch_ctrl_get_ingress_response_table
3386 (
3387     nvswitch_device *device,
3388     NVSWITCH_GET_INGRESS_RESPONSE_TABLE_PARAMS *params
3389 )
3390 {
3391     return device->hal.nvswitch_ctrl_get_ingress_response_table(device, params);
3392 }
3393 
3394 static NvlStatus
_nvswitch_ctrl_set_ingress_response_table(nvswitch_device * device,NVSWITCH_SET_INGRESS_RESPONSE_TABLE * p)3395 _nvswitch_ctrl_set_ingress_response_table
3396 (
3397     nvswitch_device *device,
3398     NVSWITCH_SET_INGRESS_RESPONSE_TABLE *p
3399 )
3400 {
3401     return device->hal.nvswitch_ctrl_set_ingress_response_table(device, p);
3402 }
3403 
3404 static NvlStatus
_nvswitch_ctrl_set_ganged_link_table(nvswitch_device * device,NVSWITCH_SET_GANGED_LINK_TABLE * p)3405 _nvswitch_ctrl_set_ganged_link_table
3406 (
3407     nvswitch_device *device,
3408     NVSWITCH_SET_GANGED_LINK_TABLE *p
3409 )
3410 {
3411     return device->hal.nvswitch_ctrl_set_ganged_link_table(device, p);
3412 }
3413 
3414 void
nvswitch_init_npg_multicast(nvswitch_device * device)3415 nvswitch_init_npg_multicast
3416 (
3417     nvswitch_device *device
3418 )
3419 {
3420     return device->hal.nvswitch_init_npg_multicast(device);
3421 }
3422 
3423 void
nvswitch_init_warm_reset(nvswitch_device * device)3424 nvswitch_init_warm_reset
3425 (
3426     nvswitch_device *device
3427 )
3428 {
3429     return device->hal.nvswitch_init_warm_reset(device);
3430 }
3431 
3432 static NvlStatus
_nvswitch_ctrl_set_remap_policy(nvswitch_device * device,NVSWITCH_SET_REMAP_POLICY * p)3433 _nvswitch_ctrl_set_remap_policy
3434 (
3435     nvswitch_device *device,
3436     NVSWITCH_SET_REMAP_POLICY *p
3437 )
3438 {
3439     return device->hal.nvswitch_ctrl_set_remap_policy(device, p);
3440 }
3441 
3442 static NvlStatus
_nvswitch_ctrl_get_remap_policy(nvswitch_device * device,NVSWITCH_GET_REMAP_POLICY_PARAMS * params)3443 _nvswitch_ctrl_get_remap_policy
3444 (
3445     nvswitch_device *device,
3446     NVSWITCH_GET_REMAP_POLICY_PARAMS *params
3447 )
3448 {
3449     return device->hal.nvswitch_ctrl_get_remap_policy(device, params);
3450 }
3451 
3452 static NvlStatus
_nvswitch_ctrl_set_remap_policy_valid(nvswitch_device * device,NVSWITCH_SET_REMAP_POLICY_VALID * p)3453 _nvswitch_ctrl_set_remap_policy_valid
3454 (
3455     nvswitch_device *device,
3456     NVSWITCH_SET_REMAP_POLICY_VALID *p
3457 )
3458 {
3459     return device->hal.nvswitch_ctrl_set_remap_policy_valid(device, p);
3460 }
3461 
3462 static NvlStatus
_nvswitch_ctrl_set_routing_id(nvswitch_device * device,NVSWITCH_SET_ROUTING_ID * p)3463 _nvswitch_ctrl_set_routing_id
3464 (
3465     nvswitch_device *device,
3466     NVSWITCH_SET_ROUTING_ID *p
3467 )
3468 {
3469     return device->hal.nvswitch_ctrl_set_routing_id(device, p);
3470 }
3471 
3472 static NvlStatus
_nvswitch_ctrl_get_routing_id(nvswitch_device * device,NVSWITCH_GET_ROUTING_ID_PARAMS * params)3473 _nvswitch_ctrl_get_routing_id
3474 (
3475     nvswitch_device *device,
3476     NVSWITCH_GET_ROUTING_ID_PARAMS *params
3477 )
3478 {
3479     return device->hal.nvswitch_ctrl_get_routing_id(device, params);
3480 }
3481 
3482 static NvlStatus
_nvswitch_ctrl_set_routing_id_valid(nvswitch_device * device,NVSWITCH_SET_ROUTING_ID_VALID * p)3483 _nvswitch_ctrl_set_routing_id_valid
3484 (
3485     nvswitch_device *device,
3486     NVSWITCH_SET_ROUTING_ID_VALID *p
3487 )
3488 {
3489     return device->hal.nvswitch_ctrl_set_routing_id_valid(device, p);
3490 }
3491 
3492 static NvlStatus
_nvswitch_ctrl_set_routing_lan(nvswitch_device * device,NVSWITCH_SET_ROUTING_LAN * p)3493 _nvswitch_ctrl_set_routing_lan
3494 (
3495     nvswitch_device *device,
3496     NVSWITCH_SET_ROUTING_LAN *p
3497 )
3498 {
3499     return device->hal.nvswitch_ctrl_set_routing_lan(device, p);
3500 }
3501 
3502 static NvlStatus
_nvswitch_ctrl_get_routing_lan(nvswitch_device * device,NVSWITCH_GET_ROUTING_LAN_PARAMS * params)3503 _nvswitch_ctrl_get_routing_lan
3504 (
3505     nvswitch_device *device,
3506     NVSWITCH_GET_ROUTING_LAN_PARAMS *params
3507 )
3508 {
3509     return device->hal.nvswitch_ctrl_get_routing_lan(device, params);
3510 }
3511 
3512 static NvlStatus
_nvswitch_ctrl_set_routing_lan_valid(nvswitch_device * device,NVSWITCH_SET_ROUTING_LAN_VALID * p)3513 _nvswitch_ctrl_set_routing_lan_valid
3514 (
3515     nvswitch_device *device,
3516     NVSWITCH_SET_ROUTING_LAN_VALID *p
3517 )
3518 {
3519     return device->hal.nvswitch_ctrl_set_routing_lan_valid(device, p);
3520 }
3521 
3522 static NvlStatus
_nvswitch_ctrl_get_internal_latency(nvswitch_device * device,NVSWITCH_GET_INTERNAL_LATENCY * p)3523 _nvswitch_ctrl_get_internal_latency
3524 (
3525     nvswitch_device *device,
3526     NVSWITCH_GET_INTERNAL_LATENCY *p
3527 )
3528 {
3529     return device->hal.nvswitch_ctrl_get_internal_latency(device, p);
3530 }
3531 
3532 static NvlStatus
_nvswitch_ctrl_get_nvlipt_counters(nvswitch_device * device,NVSWITCH_GET_NVLIPT_COUNTERS * p)3533 _nvswitch_ctrl_get_nvlipt_counters
3534 (
3535     nvswitch_device *device,
3536     NVSWITCH_GET_NVLIPT_COUNTERS *p
3537 )
3538 {
3539     //
3540     // This control call is now deprecated.
3541     // New control call to fetch throughput counters is:
3542     // nvswitch_ctrl_get_throughput_counters
3543     //
3544     return -NVL_ERR_NOT_SUPPORTED;
3545 }
3546 
3547 static NvlStatus
_nvswitch_ctrl_set_nvlipt_counter_config(nvswitch_device * device,NVSWITCH_SET_NVLIPT_COUNTER_CONFIG * p)3548 _nvswitch_ctrl_set_nvlipt_counter_config
3549 (
3550     nvswitch_device *device,
3551     NVSWITCH_SET_NVLIPT_COUNTER_CONFIG *p
3552 )
3553 {
3554     //
3555     // This control call is now deprecated.
3556     // New control call to fetch throughput counters is:
3557     // nvswitch_ctrl_get_throughput_counters_lr10
3558     //
3559     // Setting counter config is not allowed on these
3560     // non-configurable counters. These counters are
3561     // expected to be used by monitoring clients.
3562     //
3563     return -NVL_ERR_NOT_SUPPORTED;
3564 }
3565 
3566 static NvlStatus
_nvswitch_ctrl_get_nvlipt_counter_config(nvswitch_device * device,NVSWITCH_GET_NVLIPT_COUNTER_CONFIG * p)3567 _nvswitch_ctrl_get_nvlipt_counter_config
3568 (
3569     nvswitch_device *device,
3570     NVSWITCH_GET_NVLIPT_COUNTER_CONFIG *p
3571 )
3572 {
3573     //
3574     // This control call is now deprecated.
3575     // New control call to fetch throughput counters is:
3576     // nvswitch_ctrl_get_throughput_counters_lr10
3577     //
3578     // Getting counter config is useful if counters are
3579     // configurable. These counters are not configurable
3580     // and are expected to be used by monitoring clients.
3581     //
3582     return -NVL_ERR_NOT_SUPPORTED;
3583 }
3584 
3585 static NvlStatus
_nvswitch_ctrl_register_read(nvswitch_device * device,NVSWITCH_REGISTER_READ * p)3586 _nvswitch_ctrl_register_read
3587 (
3588     nvswitch_device *device,
3589     NVSWITCH_REGISTER_READ *p
3590 )
3591 {
3592     return device->hal.nvswitch_ctrl_register_read(device, p);
3593 }
3594 
3595 static NvlStatus
_nvswitch_ctrl_register_write(nvswitch_device * device,NVSWITCH_REGISTER_WRITE * p)3596 _nvswitch_ctrl_register_write
3597 (
3598     nvswitch_device *device,
3599     NVSWITCH_REGISTER_WRITE *p
3600 )
3601 {
3602     return device->hal.nvswitch_ctrl_register_write(device, p);
3603 }
3604 
3605 NvU32
nvswitch_i2c_get_port_info(nvswitch_device * device,NvU32 port)3606 nvswitch_i2c_get_port_info
3607 (
3608     nvswitch_device *device,
3609     NvU32 port
3610 )
3611 {
3612     return device->hal.nvswitch_i2c_get_port_info(device, port);
3613 }
3614 
3615 NvlStatus
nvswitch_ctrl_i2c_indexed(nvswitch_device * device,NVSWITCH_CTRL_I2C_INDEXED_PARAMS * pParams)3616 nvswitch_ctrl_i2c_indexed
3617 (
3618     nvswitch_device *device,
3619     NVSWITCH_CTRL_I2C_INDEXED_PARAMS *pParams
3620 )
3621 {
3622     return device->hal.nvswitch_ctrl_i2c_indexed(device, pParams);
3623 }
3624 
3625 static NvlStatus
_nvswitch_ctrl_therm_read_temperature(nvswitch_device * device,NVSWITCH_CTRL_GET_TEMPERATURE_PARAMS * info)3626 _nvswitch_ctrl_therm_read_temperature
3627 (
3628     nvswitch_device *device,
3629     NVSWITCH_CTRL_GET_TEMPERATURE_PARAMS *info
3630 )
3631 {
3632     return device->hal.nvswitch_ctrl_therm_read_temperature(device, info);
3633 }
3634 
3635 static NvlStatus
_nvswitch_ctrl_get_bios_info(nvswitch_device * device,NVSWITCH_GET_BIOS_INFO_PARAMS * p)3636 _nvswitch_ctrl_get_bios_info
3637 (
3638     nvswitch_device *device,
3639     NVSWITCH_GET_BIOS_INFO_PARAMS *p
3640 )
3641 {
3642     return device->hal.nvswitch_ctrl_get_bios_info(device, p);
3643 }
3644 
3645 static NvlStatus
_nvswitch_ctrl_get_inforom_version(nvswitch_device * device,NVSWITCH_GET_INFOROM_VERSION_PARAMS * p)3646 _nvswitch_ctrl_get_inforom_version
3647 (
3648     nvswitch_device *device,
3649     NVSWITCH_GET_INFOROM_VERSION_PARAMS *p
3650 )
3651 {
3652     return device->hal.nvswitch_ctrl_get_inforom_version(device, p);
3653 }
3654 
3655 NvlStatus
nvswitch_ctrl_set_latency_bins(nvswitch_device * device,NVSWITCH_SET_LATENCY_BINS * p)3656 nvswitch_ctrl_set_latency_bins
3657 (
3658     nvswitch_device *device,
3659     NVSWITCH_SET_LATENCY_BINS *p
3660 )
3661 {
3662     return device->hal.nvswitch_ctrl_set_latency_bins(device, p);
3663 }
3664 
3665 static NvlStatus
_nvswitch_ctrl_get_ingress_reqlinkid(nvswitch_device * device,NVSWITCH_GET_INGRESS_REQLINKID_PARAMS * params)3666 _nvswitch_ctrl_get_ingress_reqlinkid
3667 (
3668     nvswitch_device *device,
3669     NVSWITCH_GET_INGRESS_REQLINKID_PARAMS *params
3670 )
3671 {
3672     return device->hal.nvswitch_ctrl_get_ingress_reqlinkid(device, params);
3673 }
3674 
3675 NvlStatus
nvswitch_ctrl_get_throughput_counters(nvswitch_device * device,NVSWITCH_GET_THROUGHPUT_COUNTERS_PARAMS * p)3676 nvswitch_ctrl_get_throughput_counters
3677 (
3678     nvswitch_device *device,
3679     NVSWITCH_GET_THROUGHPUT_COUNTERS_PARAMS *p
3680 )
3681 {
3682     return device->hal.nvswitch_ctrl_get_throughput_counters(device, p);
3683 }
3684 
3685 static NvlStatus
_nvswitch_ctrl_unregister_link(nvswitch_device * device,NVSWITCH_UNREGISTER_LINK_PARAMS * params)3686 _nvswitch_ctrl_unregister_link
3687 (
3688     nvswitch_device *device,
3689     NVSWITCH_UNREGISTER_LINK_PARAMS *params
3690 )
3691 {
3692     nvlink_link *link = nvswitch_get_link(device, (NvU8)params->portNum);
3693 
3694     if (link == NULL)
3695     {
3696         return -NVL_BAD_ARGS;
3697     }
3698 
3699     // With ALI in FW, links can be unregistered while Active
3700     if (!device->nvlink_device->enableALI)
3701     {
3702 
3703     if (device->hal.nvswitch_is_link_in_use(device, params->portNum))
3704     {
3705         return -NVL_ERR_STATE_IN_USE;
3706     }
3707 
3708     }
3709 
3710     nvlink_lib_unregister_link(link);
3711     nvswitch_destroy_link(link);
3712 
3713     return NVL_SUCCESS;
3714 }
3715 
3716 static NvlStatus
_nvswitch_ctrl_acquire_capability(nvswitch_device * device,NVSWITCH_ACQUIRE_CAPABILITY_PARAMS * params,void * osPrivate)3717 _nvswitch_ctrl_acquire_capability
3718 (
3719     nvswitch_device *device,
3720     NVSWITCH_ACQUIRE_CAPABILITY_PARAMS *params,
3721     void *osPrivate
3722 )
3723 {
3724     return nvswitch_os_acquire_fabric_mgmt_cap(osPrivate,
3725                                                params->capDescriptor);
3726 }
3727 
3728 static NvlStatus
_nvswitch_ctrl_reset_and_drain_links(nvswitch_device * device,NVSWITCH_RESET_AND_DRAIN_LINKS_PARAMS * params)3729 _nvswitch_ctrl_reset_and_drain_links
3730 (
3731     nvswitch_device *device,
3732     NVSWITCH_RESET_AND_DRAIN_LINKS_PARAMS *params
3733 )
3734 {
3735     return device->hal.nvswitch_reset_and_drain_links(device, params->linkMask, NV_FALSE);
3736 }
3737 
3738 static NvlStatus
_nvswitch_ctrl_get_fom_values(nvswitch_device * device,NVSWITCH_GET_FOM_VALUES_PARAMS * ret)3739 _nvswitch_ctrl_get_fom_values
3740 (
3741     nvswitch_device *device,
3742     NVSWITCH_GET_FOM_VALUES_PARAMS *ret
3743 )
3744 {
3745     return device->hal.nvswitch_ctrl_get_fom_values(device, ret);
3746 }
3747 
3748 static NvlStatus
_nvswitch_ctrl_get_nvlink_ecc_errors(nvswitch_device * device,NVSWITCH_GET_NVLINK_ECC_ERRORS_PARAMS * params)3749 _nvswitch_ctrl_get_nvlink_ecc_errors
3750 (
3751     nvswitch_device *device,
3752     NVSWITCH_GET_NVLINK_ECC_ERRORS_PARAMS *params
3753 )
3754 {
3755     return device->hal.nvswitch_get_nvlink_ecc_errors(device, params);
3756 }
3757 
3758 static NvlStatus
_nvswitch_ctrl_set_mc_rid_table(nvswitch_device * device,NVSWITCH_SET_MC_RID_TABLE_PARAMS * p)3759 _nvswitch_ctrl_set_mc_rid_table
3760 (
3761     nvswitch_device *device,
3762     NVSWITCH_SET_MC_RID_TABLE_PARAMS *p
3763 )
3764 {
3765     return device->hal.nvswitch_ctrl_set_mc_rid_table(device, p);
3766 }
3767 
3768 static NvlStatus
_nvswitch_ctrl_get_mc_rid_table(nvswitch_device * device,NVSWITCH_GET_MC_RID_TABLE_PARAMS * p)3769 _nvswitch_ctrl_get_mc_rid_table
3770 (
3771     nvswitch_device *device,
3772     NVSWITCH_GET_MC_RID_TABLE_PARAMS *p
3773 )
3774 {
3775     return device->hal.nvswitch_ctrl_get_mc_rid_table(device, p);
3776 }
3777 
3778 static NvlStatus
_nvswitch_ctrl_set_residency_bins(nvswitch_device * device,NVSWITCH_SET_RESIDENCY_BINS * p)3779 _nvswitch_ctrl_set_residency_bins
3780 (
3781     nvswitch_device *device,
3782     NVSWITCH_SET_RESIDENCY_BINS *p
3783 )
3784 {
3785     return device->hal.nvswitch_ctrl_set_residency_bins(device, p);
3786 }
3787 
3788 static NvlStatus
_nvswitch_ctrl_get_residency_bins(nvswitch_device * device,NVSWITCH_GET_RESIDENCY_BINS * p)3789 _nvswitch_ctrl_get_residency_bins
3790 (
3791     nvswitch_device *device,
3792     NVSWITCH_GET_RESIDENCY_BINS *p
3793 )
3794 {
3795     return device->hal.nvswitch_ctrl_get_residency_bins(device, p);
3796 }
3797 
3798 static NvlStatus
_nvswitch_ctrl_get_rb_stall_busy(nvswitch_device * device,NVSWITCH_GET_RB_STALL_BUSY * p)3799 _nvswitch_ctrl_get_rb_stall_busy
3800 (
3801     nvswitch_device *device,
3802     NVSWITCH_GET_RB_STALL_BUSY *p
3803 )
3804 {
3805     return device->hal.nvswitch_ctrl_get_rb_stall_busy(device, p);
3806 }
3807 
3808 NvlStatus
nvswitch_ctrl_get_multicast_id_error_vector(nvswitch_device * device,NVSWITCH_GET_MULTICAST_ID_ERROR_VECTOR * p)3809 nvswitch_ctrl_get_multicast_id_error_vector
3810 (
3811     nvswitch_device *device,
3812     NVSWITCH_GET_MULTICAST_ID_ERROR_VECTOR *p
3813 )
3814 {
3815     return device->hal.nvswitch_ctrl_get_multicast_id_error_vector(device, p);
3816 }
3817 
3818 NvlStatus
nvswitch_ctrl_clear_multicast_id_error_vector(nvswitch_device * device,NVSWITCH_CLEAR_MULTICAST_ID_ERROR_VECTOR * p)3819 nvswitch_ctrl_clear_multicast_id_error_vector
3820 (
3821     nvswitch_device *device,
3822     NVSWITCH_CLEAR_MULTICAST_ID_ERROR_VECTOR *p
3823 )
3824 {
3825     return device->hal.nvswitch_ctrl_clear_multicast_id_error_vector(device, p);
3826 }
3827 
3828 static NvlStatus
_nvswitch_ctrl_inband_send_data(nvswitch_device * device,NVSWITCH_INBAND_SEND_DATA_PARAMS * p)3829 _nvswitch_ctrl_inband_send_data
3830 (
3831     nvswitch_device *device,
3832     NVSWITCH_INBAND_SEND_DATA_PARAMS *p
3833 )
3834 {
3835     return device->hal.nvswitch_ctrl_inband_send_data(device, p);
3836 }
3837 
3838 static NvlStatus
_nvswitch_ctrl_inband_read_data(nvswitch_device * device,NVSWITCH_INBAND_READ_DATA_PARAMS * p)3839 _nvswitch_ctrl_inband_read_data
3840 (
3841     nvswitch_device *device,
3842     NVSWITCH_INBAND_READ_DATA_PARAMS *p
3843 )
3844 {
3845     return device->hal.nvswitch_ctrl_inband_read_data(device, p);
3846 }
3847 
3848 static NvlStatus
_nvswitch_ctrl_inband_flush_data(nvswitch_device * device,NVSWITCH_INBAND_FLUSH_DATA_PARAMS * p)3849 _nvswitch_ctrl_inband_flush_data
3850 (
3851     nvswitch_device *device,
3852     NVSWITCH_INBAND_FLUSH_DATA_PARAMS *p
3853 )
3854 {
3855     NvU32 i;
3856     NvU64 enabledLinkMask;
3857 
3858     if (p->linkMask == 0)
3859     {
3860         NVSWITCH_PRINT(device, ERROR, "Nothing to clear\n");
3861         return NVL_SUCCESS;
3862     }
3863 
3864     enabledLinkMask = nvswitch_get_enabled_link_mask(device);
3865 
3866     FOR_EACH_INDEX_IN_MASK(64, i, p->linkMask)
3867     {
3868          if (nvswitch_is_link_valid(device, i) &&
3869              (enabledLinkMask & NVBIT64(i)))
3870          {
3871               //
3872               // Flush is expected to clear both persistent and non-persistent
3873               // list. FM does flush when it wants to drop (ignore) all pending
3874               // messages w/o any NACKs.
3875               //
3876               _nvswitch_inband_clear_lists(device, i,
3877                                            NV_FALSE /* Nack */,
3878                                            NV_FALSE /* Non-persistent only */);
3879          }
3880     }
3881     FOR_EACH_INDEX_IN_MASK_END;
3882 
3883     return NVL_SUCCESS;
3884 }
3885 
3886 static NvlStatus
_nvswitch_ctrl_inband_pending_data_stats(nvswitch_device * device,NVSWITCH_INBAND_PENDING_DATA_STATS_PARAMS * p)3887 _nvswitch_ctrl_inband_pending_data_stats
3888 (
3889     nvswitch_device *device,
3890     NVSWITCH_INBAND_PENDING_DATA_STATS_PARAMS *p
3891 )
3892 {
3893     NvU32 link_num;
3894     NvU64 enabledLinkMask, persistent_mask = 0, nonpersistent_mask = 0;
3895 
3896     enabledLinkMask = nvswitch_get_enabled_link_mask(device);
3897 
3898     for (link_num = 0; link_num < nvswitch_get_num_links(device); link_num++)
3899     {
3900          if (nvswitch_is_link_valid(device, link_num) &&
3901              (enabledLinkMask & NVBIT64(link_num)))
3902          {
3903               if (!nvListIsEmpty(&device->link[link_num].inbandData.persistent_list))
3904               {
3905                   persistent_mask |= NVBIT64(link_num);
3906               }
3907 
3908               if (!nvListIsEmpty(&device->link[link_num].inbandData.nonpersistent_list))
3909               {
3910                   nonpersistent_mask |= NVBIT64(link_num);
3911               }
3912          }
3913     }
3914 
3915     if (persistent_mask > 0)
3916     {
3917         p->linkMask = persistent_mask;
3918     }
3919     else
3920     {
3921         p->linkMask = nonpersistent_mask;
3922     }
3923 
3924     return NVL_SUCCESS;
3925 }
3926 
3927 static NvlStatus
_nvswitch_ctrl_get_board_part_number(nvswitch_device * device,NVSWITCH_GET_BOARD_PART_NUMBER_VECTOR * p)3928 _nvswitch_ctrl_get_board_part_number
3929 (
3930     nvswitch_device *device,
3931     NVSWITCH_GET_BOARD_PART_NUMBER_VECTOR *p
3932 )
3933 {
3934     if (IS_RTLSIM(device) || IS_EMULATION(device) || IS_FMODEL(device))
3935     {
3936         NVSWITCH_PRINT(device, INFO,
3937         "%s: Skipping retrieval of board part number on FSF\n",
3938             __FUNCTION__);
3939 
3940         nvswitch_os_memset(p, 0, sizeof(NVSWITCH_GET_BOARD_PART_NUMBER_VECTOR));
3941 
3942        return NVL_SUCCESS;
3943     }
3944     else
3945     {
3946         if (!nvswitch_is_inforom_supported(device))
3947         {
3948             NVSWITCH_PRINT(device, ERROR, "InfoROM is not supported\n");
3949             return -NVL_ERR_NOT_SUPPORTED;
3950         }
3951 
3952         return device->hal.nvswitch_ctrl_get_board_part_number(device, p);
3953     }
3954 }
3955 
3956 static NvlStatus
_nvswitch_ctrl_i2c_smbus_command(nvswitch_device * device,NVSWITCH_I2C_SMBUS_COMMAND_PARAMS * pParams)3957 _nvswitch_ctrl_i2c_smbus_command
3958 (
3959     nvswitch_device *device,
3960     NVSWITCH_I2C_SMBUS_COMMAND_PARAMS *pParams
3961 )
3962 {
3963     NvU32 port_info;
3964     NvU32 port = pParams->port;
3965     NvU8 msgLen;
3966     NvU8 cmd;
3967     NvU16 addr;
3968     NvU8 cmdType;
3969     NvU8 *pData;
3970     NvBool is_i2c_access_allowed;
3971     NvBool is_port_allowed;
3972 
3973     port_info = nvswitch_i2c_get_port_info(device, port);
3974 
3975     is_i2c_access_allowed = (device->regkeys.i2c_access_control ==
3976                              NV_SWITCH_REGKEY_I2C_ACCESS_CONTROL_ENABLE) ?
3977                                 NV_TRUE : NV_FALSE;
3978     is_port_allowed = is_i2c_access_allowed ? NV_TRUE :
3979                           FLD_TEST_DRF(_I2C, _PORTINFO, _ACCESS_ALLOWED, _TRUE,
3980                                        port_info);
3981 
3982     if (!is_port_allowed ||
3983         !FLD_TEST_DRF(_I2C, _PORTINFO, _DEFINED, _PRESENT, port_info))
3984     {
3985         NVSWITCH_PRINT(device, ERROR, "Invalid port access %d.\n", port);
3986         return NVL_BAD_ARGS;
3987     }
3988 
3989     addr = pParams->deviceAddr;
3990 
3991     switch (pParams->cmdType)
3992     {
3993         case NVSWITCH_I2C_SMBUS_CMD_QUICK:
3994         {
3995             cmd = 0;
3996             msgLen = 0;
3997             cmdType = pParams->bRead ?
3998                           NVSWITCH_I2C_CMD_SMBUS_QUICK_READ :
3999                           NVSWITCH_I2C_CMD_SMBUS_QUICK_WRITE;
4000             pData = NULL;
4001             break;
4002         }
4003         case NVSWITCH_I2C_SMBUS_CMD_BYTE:
4004         {
4005             cmd = 0;
4006             msgLen = 1;
4007             cmdType = pParams->bRead ?
4008                           NVSWITCH_I2C_CMD_READ :
4009                           NVSWITCH_I2C_CMD_WRITE;
4010             pData = (NvU8 *)&pParams->transactionData.smbusByte.message;
4011             break;
4012         }
4013         case NVSWITCH_I2C_SMBUS_CMD_BYTE_DATA:
4014         {
4015             msgLen = 1;
4016             cmd = pParams->transactionData.smbusByteData.cmd;
4017             cmdType = pParams->bRead ?
4018                           NVSWITCH_I2C_CMD_SMBUS_READ :
4019                           NVSWITCH_I2C_CMD_SMBUS_WRITE;
4020             pData = (NvU8 *)&pParams->transactionData.smbusByteData.message;
4021             break;
4022         }
4023         case NVSWITCH_I2C_SMBUS_CMD_WORD_DATA:
4024         {
4025             msgLen = 2;
4026             cmd = pParams->transactionData.smbusWordData.cmd;
4027             cmdType = pParams->bRead ?
4028                           NVSWITCH_I2C_CMD_SMBUS_READ :
4029                           NVSWITCH_I2C_CMD_SMBUS_WRITE;
4030             pData = (NvU8 *)&pParams->transactionData.smbusWordData.message;
4031             break;
4032         }
4033         default:
4034         {
4035             NVSWITCH_PRINT(device, ERROR, "Invalid Smbus command: %d.\n", port);
4036             return NVL_BAD_ARGS;
4037         }
4038     }
4039 
4040     return _nvswitch_perform_i2c_transfer(device, NVSWITCH_I2C_ACQUIRER_IOCTL,
4041                                           cmdType, addr, port, cmd, msgLen, pData);
4042 }
4043 
4044 NvBool
nvswitch_does_link_need_termination_enabled(nvswitch_device * device,nvlink_link * link)4045 nvswitch_does_link_need_termination_enabled
4046 (
4047     nvswitch_device *device,
4048     nvlink_link *link
4049 )
4050 {
4051     return device->hal.nvswitch_does_link_need_termination_enabled(device, link);
4052 }
4053 
4054 NvlStatus
nvswitch_link_termination_setup(nvswitch_device * device,nvlink_link * link)4055 nvswitch_link_termination_setup
4056 (
4057     nvswitch_device *device,
4058     nvlink_link* link
4059 )
4060 {
4061     return device->hal.nvswitch_link_termination_setup(device, link);
4062 }
4063 
4064 static NvlStatus
_nvswitch_ctrl_cci_cmis_presence(nvswitch_device * device,NVSWITCH_CCI_CMIS_PRESENCE_PARAMS * pParams)4065 _nvswitch_ctrl_cci_cmis_presence
4066 (
4067     nvswitch_device *device,
4068     NVSWITCH_CCI_CMIS_PRESENCE_PARAMS *pParams
4069 )
4070 {
4071     nvswitch_os_memset(pParams, 0, sizeof(NVSWITCH_CCI_CMIS_PRESENCE_PARAMS));
4072     if (device->pCci != NULL)
4073     {
4074         (void)cciGetXcvrMask(device, &pParams->cagesMask, &pParams->modulesMask);
4075     }
4076 
4077     // IOCTL will always succeed
4078     return NVL_SUCCESS;
4079 }
4080 
4081 static NvlStatus
_nvswitch_ctrl_cci_nvlink_mappings(nvswitch_device * device,NVSWITCH_CCI_CMIS_NVLINK_MAPPING_PARAMS * pParams)4082 _nvswitch_ctrl_cci_nvlink_mappings
4083 (
4084     nvswitch_device *device,
4085     NVSWITCH_CCI_CMIS_NVLINK_MAPPING_PARAMS *pParams
4086 )
4087 {
4088     if (device->pCci == NULL)
4089     {
4090         NVSWITCH_PRINT(device, ERROR,
4091             "%s: CCI not supported\n",
4092             __FUNCTION__);
4093         return -NVL_ERR_NOT_SUPPORTED;
4094     }
4095 
4096     return cciGetCageMapping(device, pParams->cageIndex, &pParams->linkMask, &pParams->encodedValue);
4097 }
4098 
4099 static NvlStatus
_nvswitch_ctrl_cci_memory_access_read(nvswitch_device * device,NVSWITCH_CCI_CMIS_MEMORY_ACCESS_READ_PARAMS * pParams)4100 _nvswitch_ctrl_cci_memory_access_read
4101 (
4102     nvswitch_device *device,
4103     NVSWITCH_CCI_CMIS_MEMORY_ACCESS_READ_PARAMS *pParams
4104 )
4105 {
4106     NvlStatus retVal;
4107 
4108     if (device->pCci == NULL)
4109     {
4110         NVSWITCH_PRINT(device, ERROR,
4111             "%s: CCI not supported\n",
4112             __FUNCTION__);
4113         return -NVL_ERR_NOT_SUPPORTED;
4114     }
4115 
4116     if (!cciCmisAccessTryLock(device, pParams->cageIndex))
4117     {
4118         return -NVL_ERR_STATE_IN_USE;
4119     }
4120 
4121     retVal = cciCmisRead(device, pParams->cageIndex, pParams->bank,
4122                        pParams->page, pParams->address, pParams->count,
4123                        pParams->data);
4124 
4125     if (!pParams->bSequenceLock)
4126     {
4127         cciCmisAccessReleaseLock(device, pParams->cageIndex);
4128     }
4129 
4130     return retVal;
4131 }
4132 
4133 static NvlStatus
_nvswitch_ctrl_cci_memory_access_write(nvswitch_device * device,NVSWITCH_CCI_CMIS_MEMORY_ACCESS_WRITE_PARAMS * pParams)4134 _nvswitch_ctrl_cci_memory_access_write
4135 (
4136     nvswitch_device *device,
4137     NVSWITCH_CCI_CMIS_MEMORY_ACCESS_WRITE_PARAMS *pParams
4138 )
4139 {
4140     NvlStatus retVal;
4141 
4142     if (device->pCci == NULL)
4143     {
4144         NVSWITCH_PRINT(device, ERROR,
4145             "%s: CCI not supported\n",
4146             __FUNCTION__);
4147         return -NVL_ERR_NOT_SUPPORTED;
4148     }
4149 
4150     if (!cciCmisAccessTryLock(device, pParams->cageIndex))
4151     {
4152         return -NVL_ERR_STATE_IN_USE;
4153     }
4154 
4155     retVal = cciCmisWrite(device, pParams->cageIndex, pParams->bank,
4156                         pParams->page, pParams->address, pParams->count,
4157                         pParams->data);
4158 
4159     if (!pParams->bSequenceLock)
4160     {
4161         cciCmisAccessReleaseLock(device, pParams->cageIndex);
4162     }
4163 
4164     return retVal;
4165 }
4166 
4167 static NvlStatus
_nvswitch_ctrl_cci_cage_bezel_marking(nvswitch_device * device,NVSWITCH_CCI_CMIS_CAGE_BEZEL_MARKING_PARAMS * pParams)4168 _nvswitch_ctrl_cci_cage_bezel_marking
4169 (
4170     nvswitch_device *device,
4171     NVSWITCH_CCI_CMIS_CAGE_BEZEL_MARKING_PARAMS *pParams
4172 )
4173 {
4174     if (device->pCci == NULL)
4175     {
4176         NVSWITCH_PRINT(device, ERROR,
4177             "%s: CCI not supported\n",
4178             __FUNCTION__);
4179         return -NVL_ERR_NOT_SUPPORTED;
4180     }
4181 
4182     return cciCmisCageBezelMarking(device, pParams->cageIndex, pParams->bezelMarking);
4183 }
4184 
4185 static NvlStatus
_nvswitch_ctrl_get_soe_heartbeat(nvswitch_device * device,NVSWITCH_GET_SOE_HEARTBEAT_PARAMS * pParams)4186 _nvswitch_ctrl_get_soe_heartbeat
4187 (
4188     nvswitch_device *device,
4189     NVSWITCH_GET_SOE_HEARTBEAT_PARAMS *pParams
4190 )
4191 {
4192     return device->hal.nvswitch_ctrl_get_soe_heartbeat(device, pParams);
4193 }
4194 
4195 static NvlStatus
_nvswitch_ctrl_set_continuous_ali(nvswitch_device * device,NVSWITCH_SET_CONTINUOUS_ALI_PARAMS * pParams)4196 _nvswitch_ctrl_set_continuous_ali
4197 (
4198     nvswitch_device *device,
4199     NVSWITCH_SET_CONTINUOUS_ALI_PARAMS *pParams
4200 )
4201 {
4202     device->bModeContinuousALI = pParams->bEnable;
4203     NVSWITCH_PRINT(device, INFO,
4204             "%s: Continuous ALI 0x%x\n",
4205             __FUNCTION__, device->bModeContinuousALI);
4206     return NVL_SUCCESS;
4207 }
4208 
4209 static NvlStatus
_nvswitch_ctrl_request_ali(nvswitch_device * device,NVSWITCH_REQUEST_ALI_PARAMS * pParams)4210 _nvswitch_ctrl_request_ali
4211 (
4212     nvswitch_device *device,
4213     NVSWITCH_REQUEST_ALI_PARAMS *pParams
4214 )
4215 {
4216     nvlink_link *link;
4217     NvU64 linkStateTl;
4218     NvU64 enabledLinkMask;
4219     NvU8 linkId;
4220 
4221     if (device->bModeContinuousALI)
4222     {
4223         return -NVL_ERR_INVALID_STATE;
4224     }
4225 
4226     // Only process enabled links
4227     enabledLinkMask = nvswitch_get_enabled_link_mask(device);
4228     pParams->linkMaskTrain &= enabledLinkMask;
4229 
4230     NVSWITCH_PRINT(device, INFO,
4231             "%s: ALI requested for links 0x%llx\n",
4232             __FUNCTION__, pParams->linkMaskTrain);
4233 
4234     // Handle access links
4235     FOR_EACH_INDEX_IN_MASK(64, linkId, pParams->linkMaskTrain)
4236     {
4237         // Only directly launch ALI on non-CCI managed links
4238         if (cciIsLinkManaged(device, linkId))
4239         {
4240             continue;
4241         }
4242 
4243         link = nvswitch_get_link(device, linkId);
4244         if ((link == NULL) ||
4245             !NVSWITCH_IS_LINK_ENG_VALID(device, linkId, NVLIPT_LNK) ||
4246             (linkId >= NVSWITCH_NVLINK_MAX_LINKS) ||
4247             (device->hal.nvswitch_corelib_get_tl_link_mode(link, &linkStateTl) != NVL_SUCCESS))
4248         {
4249             continue;
4250         }
4251 
4252         if (linkStateTl == NVLINK_LINKSTATE_ACTIVE_PENDING)
4253         {
4254             continue;
4255         }
4256 
4257         // Forcibly reset and re-train access links
4258         device->hal.nvswitch_reset_and_drain_links(device,
4259             NVBIT64(linkId), NV_TRUE);
4260     }
4261     FOR_EACH_INDEX_IN_MASK_END;
4262 
4263     // Ask CCI to handle trunk links
4264     nvswitch_ctrl_cci_request_ali(device, pParams);
4265 
4266     return NVL_SUCCESS;
4267 }
4268 
4269 static NvlStatus
_nvswitch_ctrl_get_inforom_nvlink_max_correctable_error_rate(nvswitch_device * device,NVSWITCH_GET_NVLINK_MAX_CORRECTABLE_ERROR_RATES_PARAMS * params)4270 _nvswitch_ctrl_get_inforom_nvlink_max_correctable_error_rate
4271 (
4272     nvswitch_device *device,
4273     NVSWITCH_GET_NVLINK_MAX_CORRECTABLE_ERROR_RATES_PARAMS *params
4274 )
4275 {
4276     return nvswitch_inforom_nvlink_get_max_correctable_error_rate(device, params);
4277 }
4278 
4279 static NvlStatus
_nvswitch_ctrl_get_inforom_nvlink_errors(nvswitch_device * device,NVSWITCH_GET_NVLINK_ERROR_COUNTS_PARAMS * params)4280 _nvswitch_ctrl_get_inforom_nvlink_errors
4281 (
4282     nvswitch_device *device,
4283     NVSWITCH_GET_NVLINK_ERROR_COUNTS_PARAMS *params
4284 )
4285 {
4286     return nvswitch_inforom_nvlink_get_errors(device, params);
4287 }
4288 
4289 static NvlStatus
_nvswitch_ctrl_get_inforom_ecc_errors(nvswitch_device * device,NVSWITCH_GET_ECC_ERROR_COUNTS_PARAMS * params)4290 _nvswitch_ctrl_get_inforom_ecc_errors
4291 (
4292     nvswitch_device *device,
4293     NVSWITCH_GET_ECC_ERROR_COUNTS_PARAMS *params
4294 )
4295 {
4296     return nvswitch_inforom_ecc_get_errors(device, params);
4297 }
4298 
4299 static NvlStatus
_nvswitch_ctrl_get_inforom_bbx_sxid(nvswitch_device * device,NVSWITCH_GET_SXIDS_PARAMS * params)4300 _nvswitch_ctrl_get_inforom_bbx_sxid
4301 (
4302     nvswitch_device *device,
4303     NVSWITCH_GET_SXIDS_PARAMS *params
4304 )
4305 {
4306     return nvswitch_inforom_bbx_get_sxid(device, params);
4307 }
4308 
4309 static NvlStatus
_nvswitch_ctrl_get_inforom_bbx_sys_info(nvswitch_device * device,NVSWITCH_GET_SYS_INFO_PARAMS * params)4310 _nvswitch_ctrl_get_inforom_bbx_sys_info
4311 (
4312     nvswitch_device *device,
4313     NVSWITCH_GET_SYS_INFO_PARAMS *params
4314 )
4315 {
4316     return nvswitch_inforom_bbx_get_data(device, RM_SOE_IFR_BBX_GET_SYS_INFO, (void *)params);
4317 }
4318 
4319 static NvlStatus
_nvswitch_ctrl_get_inforom_bbx_time_info(nvswitch_device * device,NVSWITCH_GET_TIME_INFO_PARAMS * params)4320 _nvswitch_ctrl_get_inforom_bbx_time_info
4321 (
4322     nvswitch_device *device,
4323     NVSWITCH_GET_TIME_INFO_PARAMS *params
4324 )
4325 {
4326     return nvswitch_inforom_bbx_get_data(device, RM_SOE_IFR_BBX_GET_TIME_INFO, (void *)params);
4327 }
4328 
4329 static NvlStatus
_nvswitch_ctrl_get_inforom_bbx_temp_data(nvswitch_device * device,NVSWITCH_GET_TEMP_DATA_PARAMS * params)4330 _nvswitch_ctrl_get_inforom_bbx_temp_data
4331 (
4332     nvswitch_device *device,
4333     NVSWITCH_GET_TEMP_DATA_PARAMS *params
4334 )
4335 {
4336     return nvswitch_inforom_bbx_get_data(device, RM_SOE_IFR_BBX_GET_TEMP_DATA, (void *)params);
4337 }
4338 
4339 static NvlStatus
_nvswitch_ctrl_get_inforom_bbx_temp_samples(nvswitch_device * device,NVSWITCH_GET_TEMP_SAMPLES_PARAMS * params)4340 _nvswitch_ctrl_get_inforom_bbx_temp_samples
4341 (
4342     nvswitch_device *device,
4343     NVSWITCH_GET_TEMP_SAMPLES_PARAMS *params
4344 )
4345 {
4346     return nvswitch_inforom_bbx_get_data(device, RM_SOE_IFR_BBX_GET_TEMP_SAMPLES, (void *)params);
4347 }
4348 
4349 static NvlStatus
_nvswitch_ctrl_get_nvlink_lp_counters(nvswitch_device * device,NVSWITCH_GET_NVLINK_LP_COUNTERS_PARAMS * params)4350 _nvswitch_ctrl_get_nvlink_lp_counters
4351 (
4352     nvswitch_device *device,
4353     NVSWITCH_GET_NVLINK_LP_COUNTERS_PARAMS *params
4354 )
4355 {
4356     return device->hal.nvswitch_ctrl_get_nvlink_lp_counters(device, params);
4357 }
4358 
4359 static NvlStatus
_nvswitch_ctrl_get_sw_info(nvswitch_device * device,NVSWITCH_GET_SW_INFO_PARAMS * params)4360 _nvswitch_ctrl_get_sw_info
4361 (
4362     nvswitch_device *device,
4363     NVSWITCH_GET_SW_INFO_PARAMS *params
4364 )
4365 {
4366     return device->hal.nvswitch_ctrl_get_sw_info(device, params);
4367 }
4368 
4369 static NvlStatus
_nvswitch_lib_validate_privileged_ctrl(void * osPrivate,NvU64 flags)4370 _nvswitch_lib_validate_privileged_ctrl
4371 (
4372     void *osPrivate,
4373     NvU64 flags
4374 )
4375 {
4376     if (flags & NVSWITCH_DEV_CMD_CHECK_ADMIN)
4377     {
4378         if (nvswitch_os_is_admin())
4379         {
4380             return NVL_SUCCESS;
4381         }
4382     }
4383 
4384     if (flags & NVSWITCH_DEV_CMD_CHECK_FM)
4385     {
4386         if (nvswitch_os_is_fabric_manager(osPrivate))
4387         {
4388             return NVL_SUCCESS;
4389         }
4390     }
4391 
4392     return -NVL_ERR_INSUFFICIENT_PERMISSIONS;
4393 }
4394 
4395 /*
4396  * @Brief : Copy the data from the persistant or nonpersistant list
4397  *
4398  * @Description :
4399  *
4400  * @param[in] device            NvSwitch device to contain this link
4401  * @param[out] data             Destination Data
4402  * @param[in] linkId            link number of the link
4403  * @param[out] dataSize         Size of data copied
4404  *
4405  * @returns                     NVL_SUCCESS if action succeeded,
4406  *                              -NVL_NOT_FOUND if link doesnt have data
4407  */
4408 NvlStatus
nvswitch_inband_read_data(nvswitch_device * device,NvU8 * dest,NvU32 linkId,NvU32 * dataSize)4409 nvswitch_inband_read_data
4410 (
4411     nvswitch_device *device,
4412     NvU8 *dest,
4413     NvU32 linkId,
4414     NvU32 *dataSize
4415 )
4416 {
4417     nvswitch_inband_data_list *curr = NULL;
4418     NVListRec *list;
4419 
4420     if (nvListIsEmpty(&device->link[linkId].inbandData.persistent_list) &&
4421         nvListIsEmpty(&device->link[linkId].inbandData.nonpersistent_list))
4422     {
4423         NVSWITCH_PRINT(device, ERROR, "%s: LinkId %d doesnt have any data to send\n",
4424                          __FUNCTION__, linkId);
4425         *dataSize = 0;
4426         return -NVL_NOT_FOUND;
4427     }
4428 
4429     list = nvListIsEmpty(&device->link[linkId].inbandData.persistent_list) ?
4430                          &device->link[linkId].inbandData.nonpersistent_list :
4431                          &device->link[linkId].inbandData.persistent_list;
4432 
4433     nvListForEachEntry(curr, list, entry)
4434     {
4435          *dataSize = curr->dataSize;
4436          nvswitch_os_memcpy(dest, curr->data, curr->dataSize);
4437          nvListDel(&curr->entry);
4438          nvswitch_os_free(curr);
4439          break;
4440     }
4441 
4442     return NVL_SUCCESS;
4443 }
4444 
4445 /*
4446  * @Brief : Returns NV_TRUE if the given inband msg
4447  *          needs to go to persistant list
4448  *
4449  * @Description :
4450  *
4451  * @param[in] device            NvSwitch device to contain this link
4452  * @param[in] msghdr            Header to the message
4453  *
4454  */
4455 
4456 static NvBool
nvswitch_is_message_persistent(nvswitch_device * device,nvlink_inband_msg_header_t * msghdr)4457 nvswitch_is_message_persistent
4458 (
4459     nvswitch_device *device,
4460     nvlink_inband_msg_header_t *msghdr
4461 )
4462 {
4463     // We expect only one message per received data
4464     switch(msghdr->type)
4465     {
4466         case NVLINK_INBAND_MSG_TYPE_MC_TEAM_RELEASE_REQ:
4467             return NV_TRUE;
4468         default:
4469             return NV_FALSE;
4470     }
4471 }
4472 
4473 /*
4474  * @Brief : Moves the data into persistant or nonpersistant list
4475  *
4476  * @Description :
4477  *
4478  * @param[in] device            NvSwitch device to contain this link
4479  * @param[in] linkId            link number of the link
4480  *
4481  */
4482 void
nvswitch_filter_messages(nvswitch_device * device,NvU32 linkId)4483 nvswitch_filter_messages
4484 (
4485     nvswitch_device *device,
4486     NvU32           linkId
4487 )
4488 {
4489     NvlStatus status;
4490     nvlink_inband_msg_header_t *msghdr = NULL;
4491     nvswitch_inband_data_list *msg = device->link[linkId].inbandData.message;
4492     NvU8   *buffer = device->link[linkId].inbandData.message->data;
4493     NVSWITCH_DRIVER_FABRIC_STATE driver_fabric_state = 0;
4494     NvBool bSendNackOrDrop = NV_FALSE;
4495 
4496     NVSWITCH_ASSERT(nvswitch_lib_read_fabric_state(device, NULL, NULL,
4497                                         &driver_fabric_state) == NVL_SUCCESS);
4498 
4499     msghdr = (nvlink_inband_msg_header_t*)buffer;
4500 
4501     if (nvswitch_is_message_persistent(device, msghdr))
4502     {
4503          if (nvListCount(&device->link[linkId].inbandData.persistent_list) <
4504              device->hal.nvswitch_get_max_persistent_message_count(device))
4505          {
4506          nvListAdd(&msg->entry, &device->link[linkId].inbandData.persistent_list);
4507     }
4508     else
4509     {
4510              bSendNackOrDrop = NV_TRUE;
4511          }
4512     }
4513     else
4514     {
4515          if (driver_fabric_state == NVSWITCH_DRIVER_FABRIC_STATE_CONFIGURED)
4516          {
4517               nvListAdd(&msg->entry,
4518                         &device->link[linkId].inbandData.nonpersistent_list);
4519          }
4520          else
4521          {
4522               bSendNackOrDrop = NV_TRUE;
4523          }
4524     }
4525 
4526     if (bSendNackOrDrop)
4527     {
4528         nvswitch_send_nack_or_drop(device, linkId, msghdr);
4529         nvswitch_os_free(msg);
4530     }
4531     else
4532     {
4533     status = nvswitch_lib_notify_client_events(device,
4534                                                NVSWITCH_DEVICE_EVENT_INBAND_DATA);
4535     if (status != NVL_SUCCESS)
4536     {
4537           NVSWITCH_PRINT(device, ERROR, "%s: Failed to notify INBAND_DATA event\n",
4538                          __FUNCTION__);
4539     }
4540     }
4541 
4542     device->link[linkId].inbandData.message = NULL;
4543 }
4544 
4545 /*
4546  * @Brief : Constructs an NVS link struct with the given data
4547  *
4548  * @Description :
4549  *
4550  * @param[in] device            NvSwitch device to contain this link
4551  * @param[in] link_num          link number of the link
4552  * @param[out] link             reference to store the created link into
4553  *
4554  * @returns                     NVL_SUCCESS if action succeeded,
4555  *                              -NVL_NO_MEM if memory allocation failed
4556  */
4557 NvlStatus
nvswitch_create_link(nvswitch_device * device,NvU32 link_number,nvlink_link ** link)4558 nvswitch_create_link
4559 (
4560     nvswitch_device *device,
4561     NvU32 link_number,
4562     nvlink_link **link
4563 )
4564 {
4565     NvlStatus   retval      = NVL_SUCCESS;
4566     nvlink_link *ret        = NULL;
4567     LINK_INFO   *link_info  = NULL;
4568     NvU64       ac_coupled_mask;
4569 
4570     NVSWITCH_ASSERT(nvswitch_get_num_links(device) <=  NVSWITCH_MAX_NUM_LINKS);
4571 
4572     ret = nvswitch_os_malloc(sizeof(*ret));
4573     if (NULL == ret)
4574     {
4575         NVSWITCH_PRINT(device, ERROR,
4576             "nvswitch_os_malloc during link creation failed!\n");
4577         retval = -NVL_NO_MEM;
4578         goto nvswitch_create_link_cleanup;
4579     }
4580     nvswitch_os_memset(ret, 0, sizeof(*ret));
4581 
4582     link_info = nvswitch_os_malloc(sizeof(*link_info));
4583     if (NULL == link_info)
4584     {
4585         NVSWITCH_PRINT(device, ERROR,
4586             "nvswitch_os_malloc during link creation failed!\n");
4587         retval = -NVL_NO_MEM;
4588         goto nvswitch_create_link_cleanup;
4589     }
4590     nvswitch_os_memset(link_info, 0, sizeof(*link_info));
4591     nvswitch_os_snprintf(link_info->name, sizeof(link_info->name), NVSWITCH_LINK_NAME "%d", link_number);
4592 
4593     ret->dev        = device->nvlink_device;
4594     ret->linkName   = link_info->name;
4595     ret->linkNumber = link_number;
4596     ret->state      = NVLINK_LINKSTATE_OFF;
4597     ret->ac_coupled = NV_FALSE;
4598     ret->version    = nvswitch_get_link_ip_version(device, link_number);
4599 
4600     ac_coupled_mask = ((NvU64)device->regkeys.ac_coupled_mask2 << 32 |
4601                        (NvU64)device->regkeys.ac_coupled_mask);
4602 
4603     if (ac_coupled_mask)
4604     {
4605         if (ac_coupled_mask & NVBIT64(link_number))
4606         {
4607             ret->ac_coupled = NV_TRUE;
4608         }
4609     }
4610     else if (device->firmware.nvlink.link_config_found)
4611     {
4612         if (device->firmware.nvlink.link_ac_coupled_mask & NVBIT64(link_number))
4613         {
4614             ret->ac_coupled = NV_TRUE;
4615         }
4616     }
4617 
4618     // Initialize NVLink corelib callbacks for switch
4619     nvswitch_get_link_handlers(&link_handlers);
4620 
4621     ret->link_handlers = &link_handlers;
4622 
4623     //
4624     // link_info is used to store private link information
4625     //
4626 
4627     ret->link_info = link_info;
4628 
4629     *link = ret;
4630 
4631     return retval;
4632 
4633 nvswitch_create_link_cleanup:
4634     if (NULL != ret)
4635     {
4636         nvswitch_os_free(ret);
4637     }
4638     if (NULL != link_info)
4639     {
4640         nvswitch_os_free(link_info);
4641     }
4642 
4643     return retval;
4644 }
4645 
4646 void
nvswitch_destroy_link(nvlink_link * link)4647 nvswitch_destroy_link
4648 (
4649     nvlink_link *link
4650 )
4651 {
4652     if (NULL != link->link_info)
4653     {
4654         nvswitch_os_free(link->link_info);
4655     }
4656 
4657     nvswitch_os_free(link);
4658 }
4659 
4660 NvU32
nvswitch_get_num_links(nvswitch_device * device)4661 nvswitch_get_num_links
4662 (
4663     nvswitch_device *device
4664 )
4665 {
4666     return device->hal.nvswitch_get_num_links(device);
4667 }
4668 
4669 NvBool
nvswitch_is_link_valid(nvswitch_device * device,NvU32 link_id)4670 nvswitch_is_link_valid
4671 (
4672     nvswitch_device *device,
4673     NvU32            link_id
4674 )
4675 {
4676     return device->hal.nvswitch_is_link_valid(device, link_id);
4677 }
4678 
4679 nvlink_link*
nvswitch_get_link(nvswitch_device * device,NvU8 link_id)4680 nvswitch_get_link(nvswitch_device *device, NvU8 link_id)
4681 {
4682     nvlink_link *link = NULL;
4683 
4684     nvlink_lib_get_link(device->nvlink_device, link_id, &link);
4685 
4686     return link;
4687 }
4688 
4689 NvU64
nvswitch_get_enabled_link_mask(nvswitch_device * device)4690 nvswitch_get_enabled_link_mask
4691 (
4692     nvswitch_device *device
4693 )
4694 {
4695     NvU64                    ret;
4696     nvlink_link             *link;
4697     NvU32 link_num;
4698 
4699     ret = 0x0;
4700 
4701     for (link_num = 0; link_num < nvswitch_get_num_links(device); link_num++)
4702     {
4703         if (nvlink_lib_get_link(device->nvlink_device, link_num, &link) == NVL_SUCCESS)
4704         {
4705             ret |= NVBIT64(link_num);
4706         }
4707     }
4708 
4709     return ret;
4710 }
4711 
4712 void
nvswitch_set_fatal_error(nvswitch_device * device,NvBool device_fatal,NvU32 link_id)4713 nvswitch_set_fatal_error
4714 (
4715     nvswitch_device *device,
4716     NvBool           device_fatal,
4717     NvU32            link_id
4718 )
4719 {
4720     device->hal.nvswitch_set_fatal_error(device, device_fatal, link_id);
4721 }
4722 
4723 NvU32
nvswitch_get_swap_clk_default(nvswitch_device * device)4724 nvswitch_get_swap_clk_default
4725 (
4726     nvswitch_device *device
4727 )
4728 {
4729     return device->hal.nvswitch_get_swap_clk_default(device);
4730 }
4731 
4732 NvU32
nvswitch_get_latency_sample_interval_msec(nvswitch_device * device)4733 nvswitch_get_latency_sample_interval_msec
4734 (
4735     nvswitch_device *device
4736 )
4737 {
4738     return device->hal.nvswitch_get_latency_sample_interval_msec(device);
4739 }
4740 
4741 void
nvswitch_internal_latency_bin_log(nvswitch_device * device)4742 nvswitch_internal_latency_bin_log
4743 (
4744     nvswitch_device *device
4745 )
4746 {
4747     device->hal.nvswitch_internal_latency_bin_log(device);
4748 }
4749 
4750 void
nvswitch_ecc_writeback_task(nvswitch_device * device)4751 nvswitch_ecc_writeback_task
4752 (
4753     nvswitch_device *device
4754 )
4755 {
4756     device->hal.nvswitch_ecc_writeback_task(device);
4757 }
4758 
4759 void
nvswitch_monitor_thermal_alert(nvswitch_device * device)4760 nvswitch_monitor_thermal_alert
4761 (
4762     nvswitch_device *device
4763 )
4764 {
4765     device->hal.nvswitch_monitor_thermal_alert(device);
4766 }
4767 
4768 void
nvswitch_hw_counter_shutdown(nvswitch_device * device)4769 nvswitch_hw_counter_shutdown
4770 (
4771     nvswitch_device *device
4772 )
4773 {
4774     device->hal.nvswitch_hw_counter_shutdown(device);
4775 }
4776 
4777 NvlStatus
nvswitch_get_rom_info(nvswitch_device * device,NVSWITCH_EEPROM_TYPE * eeprom)4778 nvswitch_get_rom_info
4779 (
4780     nvswitch_device *device,
4781     NVSWITCH_EEPROM_TYPE *eeprom
4782 )
4783 {
4784     return device->hal.nvswitch_get_rom_info(device, eeprom);
4785 }
4786 
4787 void
nvswitch_lib_enable_interrupts(nvswitch_device * device)4788 nvswitch_lib_enable_interrupts
4789 (
4790     nvswitch_device *device
4791 )
4792 {
4793     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
4794     {
4795         NVSWITCH_ASSERT(0);
4796         return;
4797     }
4798 
4799     device->hal.nvswitch_lib_enable_interrupts(device);
4800 }
4801 
4802 void
nvswitch_lib_disable_interrupts(nvswitch_device * device)4803 nvswitch_lib_disable_interrupts
4804 (
4805     nvswitch_device *device
4806 )
4807 {
4808     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
4809     {
4810         NVSWITCH_ASSERT(0);
4811         return;
4812     }
4813 
4814     device->hal.nvswitch_lib_disable_interrupts(device);
4815 }
4816 
4817 NvlStatus
nvswitch_lib_check_interrupts(nvswitch_device * device)4818 nvswitch_lib_check_interrupts
4819 (
4820     nvswitch_device *device
4821 )
4822 {
4823     if (!NVSWITCH_IS_DEVICE_INITIALIZED(device))
4824     {
4825         return -NVL_BAD_ARGS;
4826     }
4827 
4828     return device->hal.nvswitch_lib_check_interrupts(device);
4829 }
4830 
4831 NvlStatus
nvswitch_lib_service_interrupts(nvswitch_device * device)4832 nvswitch_lib_service_interrupts
4833 (
4834     nvswitch_device *device
4835 )
4836 {
4837     if (!NVSWITCH_IS_DEVICE_INITIALIZED(device))
4838     {
4839         return -NVL_BAD_ARGS;
4840     }
4841 
4842     return device->hal.nvswitch_lib_service_interrupts(device);
4843 }
4844 
4845 NvU64
nvswitch_hw_counter_read_counter(nvswitch_device * device)4846 nvswitch_hw_counter_read_counter
4847 (
4848     nvswitch_device *device
4849 )
4850 {
4851     return device->hal.nvswitch_hw_counter_read_counter(device);
4852 }
4853 
4854 NvU32
nvswitch_get_link_ip_version(nvswitch_device * device,NvU32 link_id)4855 nvswitch_get_link_ip_version
4856 (
4857     nvswitch_device *device,
4858     NvU32            link_id
4859 )
4860 {
4861     return device->hal.nvswitch_get_link_ip_version(device, link_id);
4862 }
4863 
4864 NvU32
nvswitch_reg_read_32(nvswitch_device * device,NvU32 offset)4865 nvswitch_reg_read_32
4866 (
4867     nvswitch_device *device,
4868     NvU32 offset
4869 )
4870 {
4871     NvU32 val;
4872 
4873     if (device->nvlink_device->pciInfo.bars[0].pBar == NULL)
4874     {
4875         NVSWITCH_PRINT(device, ERROR,
4876             "register read failed at offset 0x%x\n", offset);
4877 
4878         return 0xFFFFFFFF;
4879     }
4880 
4881     val = nvswitch_os_mem_read32((NvU8 *)device->nvlink_device->pciInfo.bars[0].pBar + offset);
4882 
4883     if ((val & 0xFFFF0000) == 0xBADF0000)
4884     {
4885         NvU32 boot_0;
4886         NVSWITCH_PRINT(device, WARN,
4887             "Potential IO failure reading 0x%x (0x%x)\n", offset, val);
4888         boot_0 = nvswitch_os_mem_read32((NvU8 *)device->nvlink_device->pciInfo.bars[0].pBar + 0x0);
4889 
4890         if ((boot_0 & 0xFFFF0000) == 0xBADF0000)
4891         {
4892             NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_IO_FAILURE,
4893                 "IO failure\n");
4894             NVSWITCH_PRINT(device, ERROR,
4895                 "IO failure reading 0x%x (0x%x)\n", offset, val);
4896         }
4897     }
4898 
4899 #ifdef _VERBOSE_REG_ACCESS
4900     NVSWITCH_PRINT(device, SETUP,
4901         "NVSWITCH read 0x%6x+%6x = 0x%08x\n",
4902         device->nvlink_device->pciInfo.bars[0].baseAddr, offset, val);
4903 #endif
4904 
4905     return val;
4906 }
4907 
4908 void
nvswitch_reg_write_32(nvswitch_device * device,NvU32 offset,NvU32 data)4909 nvswitch_reg_write_32
4910 (
4911     nvswitch_device *device,
4912     NvU32 offset,
4913     NvU32 data
4914 )
4915 {
4916     if (device->nvlink_device->pciInfo.bars[0].pBar == NULL)
4917     {
4918         NVSWITCH_PRINT(device, ERROR,
4919             "register write failed at offset 0x%x\n", offset);
4920 
4921         return;
4922     }
4923 
4924 #ifdef _VERBOSE_REG_ACCESS
4925     NVSWITCH_PRINT(device, SETUP,
4926         "NVSWITCH write 0x%6x+%6x = 0x%08x\n",
4927         device->nvlink_device->pciInfo.bars[0].baseAddr, offset, data);
4928 #endif
4929 
4930     // Write the register
4931     nvswitch_os_mem_write32((NvU8 *)device->nvlink_device->pciInfo.bars[0].pBar + offset, data);
4932 
4933     return;
4934 }
4935 
4936 NvU64
nvswitch_read_64bit_counter(nvswitch_device * device,NvU32 lo_offset,NvU32 hi_offset)4937 nvswitch_read_64bit_counter
4938 (
4939     nvswitch_device *device,
4940     NvU32 lo_offset,
4941     NvU32 hi_offset
4942 )
4943 {
4944     NvU32   hi0;
4945     NvU32   hi1;
4946     NvU32   lo;
4947 
4948     hi0 = nvswitch_reg_read_32(device, hi_offset);
4949     do
4950     {
4951         hi1 = hi0;
4952         lo  = nvswitch_reg_read_32(device, lo_offset);
4953         hi0 = nvswitch_reg_read_32(device, hi_offset);
4954     } while (hi0 != hi1);
4955 
4956     return (lo | ((NvU64)hi0 << 32));
4957 }
4958 
4959 NvlStatus
nvswitch_validate_pll_config(nvswitch_device * device,NVSWITCH_PLL_INFO * switch_pll,NVSWITCH_PLL_LIMITS default_pll_limits)4960 nvswitch_validate_pll_config
4961 (
4962     nvswitch_device *device,
4963     NVSWITCH_PLL_INFO *switch_pll,
4964     NVSWITCH_PLL_LIMITS default_pll_limits
4965 )
4966 {
4967     NvU32 update_rate_khz;
4968     NvU32 vco_freq_khz;
4969     NVSWITCH_PLL_LIMITS pll_limits;
4970 
4971     NVSWITCH_PRINT(device, SETUP,
4972         "%s: Validating PLL: %dkHz * %d / (%d * %d * (1 << %d))\n",
4973         __FUNCTION__,
4974         switch_pll->src_freq_khz,
4975         switch_pll->N,
4976         switch_pll->M,
4977         switch_pll->PL,
4978         switch_pll->dist_mode);
4979 
4980     //
4981     // These parameters could come from schmoo'ing API, settings file or a ROM.
4982     // For now, hard code with POR.
4983     //
4984     if (device->firmware.firmware_size > 0 &&
4985         device->firmware.clocks.clocks_found &&
4986         device->firmware.clocks.sys_pll.valid)
4987     {
4988         pll_limits = device->firmware.clocks.sys_pll;
4989     }
4990     else
4991     {
4992         pll_limits = default_pll_limits;
4993     }
4994 
4995     NVSWITCH_ASSERT(switch_pll->M != 0);
4996     NVSWITCH_ASSERT(switch_pll->PL != 0);
4997 
4998     if ((switch_pll->src_freq_khz < pll_limits.ref_min_mhz * 1000) ||
4999         (switch_pll->src_freq_khz > pll_limits.ref_max_mhz * 1000))
5000     {
5001         NVSWITCH_PRINT(device, ERROR,
5002             "%s: ERROR: Ref(%d) out-of-range\n",
5003             __FUNCTION__,
5004             switch_pll->src_freq_khz);
5005         return -NVL_ERR_INVALID_STATE;
5006     }
5007 
5008     if ((switch_pll->M < pll_limits.m_min) ||
5009         (switch_pll->M > pll_limits.m_max))
5010     {
5011         NVSWITCH_PRINT(device, ERROR,
5012             "%s: ERROR: M(%d) out-of-range\n",
5013             __FUNCTION__,
5014             switch_pll->M);
5015         return -NVL_ERR_INVALID_STATE;
5016     }
5017 
5018     if ((switch_pll->N < pll_limits.n_min) ||
5019         (switch_pll->N > pll_limits.n_max))
5020     {
5021         NVSWITCH_PRINT(device, ERROR,
5022             "%s: ERROR: N(%d) out-of-range\n",
5023             __FUNCTION__,
5024             switch_pll->N);
5025         return -NVL_ERR_INVALID_STATE;
5026     }
5027 
5028     if ((switch_pll->PL < pll_limits.pl_min) ||
5029         (switch_pll->PL > pll_limits.pl_max))
5030     {
5031         NVSWITCH_PRINT(device, ERROR,
5032             "%s: ERROR: PL(%d) out-of-range\n",
5033             __FUNCTION__,
5034             switch_pll->PL);
5035         return -NVL_ERR_INVALID_STATE;
5036     }
5037 
5038     vco_freq_khz = switch_pll->src_freq_khz * switch_pll->N
5039         / switch_pll->M;
5040     if ((vco_freq_khz < pll_limits.vco_min_mhz * 1000) ||
5041         (vco_freq_khz > pll_limits.vco_max_mhz * 1000))
5042     {
5043         NVSWITCH_PRINT(device, ERROR,
5044             "%s: ERROR: VCO(%d) freq out-of-range\n",
5045             __FUNCTION__,
5046             vco_freq_khz);
5047         return -NVL_ERR_INVALID_STATE;
5048     }
5049 
5050     update_rate_khz = switch_pll->src_freq_khz / switch_pll->M;
5051     if ((update_rate_khz < pll_limits.update_min_mhz * 1000) ||
5052         (update_rate_khz > pll_limits.update_max_mhz * 1000))
5053     {
5054         NVSWITCH_PRINT(device, ERROR,
5055             "%s: ERROR: update rate(%d) out-of-range\n",
5056             __FUNCTION__,
5057             update_rate_khz);
5058         return -NVL_ERR_INVALID_STATE;
5059     }
5060 
5061     switch_pll->vco_freq_khz = vco_freq_khz;
5062 
5063     switch_pll->freq_khz =
5064         switch_pll->src_freq_khz * switch_pll->N /
5065         (switch_pll->M * switch_pll->PL * (1 << switch_pll->dist_mode));
5066 
5067     NVSWITCH_PRINT(device, SETUP,
5068         "%s: Validated PLL: %dkHz * %d / (%d * %d * (1 << %d)) = %dkHz\n",
5069         __FUNCTION__,
5070         switch_pll->src_freq_khz,
5071         switch_pll->N,
5072         switch_pll->M,
5073         switch_pll->PL,
5074         switch_pll->dist_mode,
5075         switch_pll->freq_khz);
5076 
5077     return NVL_SUCCESS;
5078 }
5079 
5080 NvlStatus
nvswitch_init_pll_config(nvswitch_device * device)5081 nvswitch_init_pll_config
5082 (
5083     nvswitch_device *device
5084 )
5085 {
5086     return device->hal.nvswitch_init_pll_config(device);
5087 }
5088 
5089 NvlStatus
nvswitch_init_pll(nvswitch_device * device)5090 nvswitch_init_pll
5091 (
5092     nvswitch_device *device
5093 )
5094 {
5095     return device->hal.nvswitch_init_pll(device);
5096 }
5097 
5098 void
nvswitch_init_clock_gating(nvswitch_device * device)5099 nvswitch_init_clock_gating
5100 (
5101     nvswitch_device *device
5102 )
5103 {
5104     return device->hal.nvswitch_init_clock_gating(device);
5105 }
5106 
5107 void
nvswitch_lib_get_uuid(nvswitch_device * device,NvUuid * uuid)5108 nvswitch_lib_get_uuid
5109 (
5110     nvswitch_device *device,
5111     NvUuid *uuid
5112 )
5113 {
5114     if (!NVSWITCH_IS_DEVICE_INITIALIZED(device) || (uuid == NULL))
5115     {
5116         return;
5117     }
5118 
5119     nvswitch_os_memcpy(uuid, &device->uuid, sizeof(device->uuid));
5120 }
5121 
5122 NvlStatus
nvswitch_lib_get_physid(nvswitch_device * device,NvU32 * phys_id)5123 nvswitch_lib_get_physid
5124 (
5125     nvswitch_device *device,
5126     NvU32 *phys_id
5127 )
5128 {
5129     NVSWITCH_GET_INFO get_info;
5130     NvlStatus ret;
5131 
5132     if (phys_id == NULL || !NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
5133     {
5134         return -NVL_BAD_ARGS;
5135     }
5136 
5137     get_info.count=1;
5138     get_info.index[0] = NVSWITCH_GET_INFO_INDEX_PHYSICAL_ID;
5139 
5140     ret = _nvswitch_ctrl_get_info(device, &get_info);
5141     if (ret != NVL_SUCCESS)
5142     {
5143         NVSWITCH_PRINT(device, ERROR,
5144             "Failed to get physical ID\n");
5145         return ret;
5146     }
5147 
5148     *phys_id = get_info.info[0];
5149 
5150     return NVL_SUCCESS;
5151 }
5152 
5153 void
nvswitch_i2c_set_hw_speed_mode(nvswitch_device * device,NvU32 port,NvU32 speedMode)5154 nvswitch_i2c_set_hw_speed_mode
5155 (
5156     nvswitch_device *device,
5157     NvU32 port,
5158     NvU32 speedMode
5159 )
5160 {
5161     device->hal.nvswitch_i2c_set_hw_speed_mode(device, port, speedMode);
5162     return;
5163 }
5164 
5165 void
nvswitch_lib_smbpbi_log_sxid(nvswitch_device * device,NvU32 sxid,const char * pFormat,...)5166 nvswitch_lib_smbpbi_log_sxid
5167 (
5168     nvswitch_device *device,
5169     NvU32           sxid,
5170     const char      *pFormat,
5171     ...
5172 )
5173 {
5174     va_list arglist;
5175     int     msglen;
5176     char    string[RM_SOE_SMBPBI_CMD_LOG_MESSAGE_MAX_STRING + 1];
5177 
5178     nvswitch_os_memset(string, 0, (NvLength)sizeof(string));
5179 
5180     va_start(arglist, pFormat);
5181     msglen = nvswitch_os_vsnprintf(string, sizeof(string), pFormat, arglist);
5182     va_end(arglist);
5183 
5184     if (!(msglen < 0))
5185     {
5186         //
5187         // HALs will know that the string is being truncated by seeing that the
5188         // last byte in the buffer is not nul.
5189         //
5190         msglen = NV_MIN(msglen + 1, (int)RM_SOE_SMBPBI_CMD_LOG_MESSAGE_MAX_STRING);
5191         device->hal.nvswitch_smbpbi_log_message(device, sxid, msglen, (NvU8 *) string);
5192     }
5193 }
5194 
5195 NvlStatus
nvswitch_set_minion_initialized(nvswitch_device * device,NvU32 idx_minion,NvBool initialized)5196 nvswitch_set_minion_initialized
5197 (
5198     nvswitch_device *device,
5199     NvU32 idx_minion,
5200     NvBool initialized
5201 )
5202 {
5203     return device->hal.nvswitch_set_minion_initialized(device, idx_minion, initialized);
5204 }
5205 
5206 NvBool
nvswitch_is_minion_initialized(nvswitch_device * device,NvU32 idx_minion)5207 nvswitch_is_minion_initialized
5208 (
5209     nvswitch_device *device,
5210     NvU32 idx_minion
5211 )
5212 {
5213     return device->hal.nvswitch_is_minion_initialized(device, idx_minion);
5214 }
5215 
5216 NvlStatus
nvswitch_device_discovery(nvswitch_device * device,NvU32 discovery_offset)5217 nvswitch_device_discovery
5218 (
5219     nvswitch_device *device,
5220     NvU32 discovery_offset
5221 )
5222 {
5223     return device->hal.nvswitch_device_discovery(device, discovery_offset);
5224 }
5225 
5226 void
nvswitch_filter_discovery(nvswitch_device * device)5227 nvswitch_filter_discovery
5228 (
5229     nvswitch_device *device
5230 )
5231 {
5232     device->hal.nvswitch_filter_discovery(device);
5233 }
5234 
5235 NvlStatus
nvswitch_process_discovery(nvswitch_device * device)5236 nvswitch_process_discovery
5237 (
5238     nvswitch_device *device
5239 )
5240 {
5241     return device->hal.nvswitch_process_discovery(device);
5242 }
5243 
5244 NvlStatus
nvswitch_init_minion(nvswitch_device * device)5245 nvswitch_init_minion
5246 (
5247     nvswitch_device *device
5248 )
5249 {
5250     return device->hal.nvswitch_init_minion(device);
5251 }
5252 
5253 NvU32
nvswitch_get_link_eng_inst(nvswitch_device * device,NvU32 link_id,NVSWITCH_ENGINE_ID eng_id)5254 nvswitch_get_link_eng_inst
5255 (
5256     nvswitch_device *device,
5257     NvU32 link_id,
5258     NVSWITCH_ENGINE_ID eng_id
5259 )
5260 {
5261     return device->hal.nvswitch_get_link_eng_inst(device, link_id, eng_id);
5262 }
5263 
5264 void *
nvswitch_alloc_chipdevice(nvswitch_device * device)5265 nvswitch_alloc_chipdevice
5266 (
5267     nvswitch_device *device
5268 )
5269 {
5270     return(device->hal.nvswitch_alloc_chipdevice(device));
5271 }
5272 
5273 void
nvswitch_free_chipdevice(nvswitch_device * device)5274 nvswitch_free_chipdevice
5275 (
5276     nvswitch_device *device
5277 )
5278 {
5279     if (device->chip_device)
5280     {
5281         nvswitch_os_free(device->chip_device);
5282         device->chip_device = NULL;
5283     }
5284 }
5285 
5286 NvlStatus
nvswitch_init_thermal(nvswitch_device * device)5287 nvswitch_init_thermal
5288 (
5289     nvswitch_device *device
5290 )
5291 {
5292     return(device->hal.nvswitch_init_thermal(device));
5293 }
5294 
5295 NvU32
nvswitch_read_physical_id(nvswitch_device * device)5296 nvswitch_read_physical_id
5297 (
5298     nvswitch_device *device
5299 )
5300 {
5301     return(device->hal.nvswitch_read_physical_id(device));
5302 }
5303 
5304 NvU32
nvswitch_get_caps_nvlink_version(nvswitch_device * device)5305 nvswitch_get_caps_nvlink_version
5306 (
5307     nvswitch_device *device
5308 )
5309 {
5310     return(device->hal.nvswitch_get_caps_nvlink_version(device));
5311 }
5312 
5313 void
nvswitch_initialize_interrupt_tree(nvswitch_device * device)5314 nvswitch_initialize_interrupt_tree
5315 (
5316     nvswitch_device *device
5317 )
5318 {
5319     device->hal.nvswitch_initialize_interrupt_tree(device);
5320 }
5321 
5322 void
nvswitch_init_dlpl_interrupts(nvlink_link * link)5323 nvswitch_init_dlpl_interrupts
5324 (
5325     nvlink_link *link
5326 )
5327 {
5328     nvswitch_device *device = link->dev->pDevInfo;
5329 
5330     device->hal.nvswitch_init_dlpl_interrupts(link);
5331 }
5332 
5333 NvlStatus
nvswitch_initialize_pmgr(nvswitch_device * device)5334 nvswitch_initialize_pmgr
5335 (
5336     nvswitch_device *device
5337 )
5338 {
5339     return(device->hal.nvswitch_initialize_pmgr(device));
5340 }
5341 
5342 NvlStatus
nvswitch_initialize_ip_wrappers(nvswitch_device * device)5343 nvswitch_initialize_ip_wrappers
5344 (
5345     nvswitch_device *device
5346 )
5347 {
5348     return(device->hal.nvswitch_initialize_ip_wrappers(device));
5349 }
5350 
5351 NvlStatus
nvswitch_initialize_route(nvswitch_device * device)5352 nvswitch_initialize_route
5353 (
5354     nvswitch_device *device
5355 )
5356 {
5357     return(device->hal.nvswitch_initialize_route(device));
5358 }
5359 
5360 void
nvswitch_soe_unregister_events(nvswitch_device * device)5361 nvswitch_soe_unregister_events
5362 (
5363     nvswitch_device *device
5364 )
5365 {
5366     device->hal.nvswitch_soe_unregister_events(device);
5367 }
5368 
5369 NvlStatus
nvswitch_soe_register_event_callbacks(nvswitch_device * device)5370 nvswitch_soe_register_event_callbacks
5371 (
5372     nvswitch_device *device
5373 )
5374 {
5375     return device->hal.nvswitch_soe_register_event_callbacks(device);
5376 }
5377 
5378 NVSWITCH_BIOS_NVLINK_CONFIG *
nvswitch_get_bios_nvlink_config(nvswitch_device * device)5379 nvswitch_get_bios_nvlink_config
5380 (
5381     nvswitch_device *device
5382 )
5383 {
5384     return(device->hal.nvswitch_get_bios_nvlink_config(device));
5385 }
5386 
5387 NvlStatus
nvswitch_minion_send_command(nvswitch_device * device,NvU32 linkNumber,NvU32 command,NvU32 scratch0)5388 nvswitch_minion_send_command
5389 (
5390     nvswitch_device *device,
5391     NvU32            linkNumber,
5392     NvU32            command,
5393     NvU32            scratch0
5394 )
5395 {
5396     return(device->hal.nvswitch_minion_send_command(device, linkNumber,
5397                                                     command, scratch0));
5398 }
5399 
5400 NvlStatus
nvswitch_init_nport(nvswitch_device * device)5401 nvswitch_init_nport
5402 (
5403     nvswitch_device *device
5404 )
5405 {
5406     return device->hal.nvswitch_init_nport(device);
5407 }
5408 
5409 NvlStatus
nvswitch_init_nxbar(nvswitch_device * device)5410 nvswitch_init_nxbar
5411 (
5412     nvswitch_device *device
5413 )
5414 {
5415     return device->hal.nvswitch_init_nxbar(device);
5416 }
5417 
5418 NvlStatus
nvswitch_clear_nport_rams(nvswitch_device * device)5419 nvswitch_clear_nport_rams
5420 (
5421     nvswitch_device *device
5422 )
5423 {
5424     return device->hal.nvswitch_clear_nport_rams(device);
5425 }
5426 
5427 NvlStatus
nvswitch_pri_ring_init(nvswitch_device * device)5428 nvswitch_pri_ring_init
5429 (
5430     nvswitch_device *device
5431 )
5432 {
5433     return(device->hal.nvswitch_pri_ring_init(device));
5434 }
5435 
5436 NvlStatus
nvswitch_get_remap_table_selector(nvswitch_device * device,NVSWITCH_TABLE_SELECT_REMAP table_selector,NvU32 * remap_ram_sel)5437 nvswitch_get_remap_table_selector
5438 (
5439     nvswitch_device *device,
5440     NVSWITCH_TABLE_SELECT_REMAP table_selector,
5441     NvU32 *remap_ram_sel
5442 )
5443 {
5444     return device->hal.nvswitch_get_remap_table_selector(device, table_selector, remap_ram_sel);
5445 }
5446 
5447 NvU32
nvswitch_get_ingress_ram_size(nvswitch_device * device,NvU32 ingress_ram_selector)5448 nvswitch_get_ingress_ram_size
5449 (
5450     nvswitch_device *device,
5451     NvU32 ingress_ram_selector      // NV_INGRESS_REQRSPMAPADDR_RAM_ADDRESS_*
5452 )
5453 {
5454     return device->hal.nvswitch_get_ingress_ram_size(device, ingress_ram_selector);
5455 }
5456 
5457 NvlStatus
nvswitch_minion_get_dl_status(nvswitch_device * device,NvU32 linkId,NvU32 statusIdx,NvU32 statusArgs,NvU32 * statusData)5458 nvswitch_minion_get_dl_status
5459 (
5460     nvswitch_device *device,
5461     NvU32            linkId,
5462     NvU32            statusIdx,
5463     NvU32            statusArgs,
5464     NvU32           *statusData
5465 )
5466 {
5467     return device->hal.nvswitch_minion_get_dl_status(device, linkId, statusIdx, statusArgs, statusData);
5468 }
5469 
5470 NvBool
nvswitch_is_i2c_supported(nvswitch_device * device)5471 nvswitch_is_i2c_supported
5472 (
5473     nvswitch_device *device
5474 )
5475 {
5476     return device->hal.nvswitch_is_i2c_supported(device);
5477 }
5478 
5479 
5480 NvlStatus
nvswitch_poll_sublink_state(nvswitch_device * device,nvlink_link * link)5481 nvswitch_poll_sublink_state
5482 (
5483     nvswitch_device *device,
5484     nvlink_link *link
5485 )
5486 {
5487     return device->hal.nvswitch_poll_sublink_state(device, link);
5488 }
5489 
5490 void
nvswitch_setup_link_loopback_mode(nvswitch_device * device,NvU32 linkNumber)5491 nvswitch_setup_link_loopback_mode
5492 (
5493     nvswitch_device *device,
5494     NvU32            linkNumber
5495 )
5496 {
5497     return device->hal.nvswitch_setup_link_loopback_mode(device, linkNumber);
5498 }
5499 
5500 void
nvswitch_reset_persistent_link_hw_state(nvswitch_device * device,NvU32 linkNumber)5501 nvswitch_reset_persistent_link_hw_state
5502 (
5503     nvswitch_device *device,
5504     NvU32            linkNumber
5505 )
5506 {
5507     return device->hal.nvswitch_reset_persistent_link_hw_state(device, linkNumber);
5508 }
5509 
5510 void
nvswitch_store_topology_information(nvswitch_device * device,nvlink_link * link)5511 nvswitch_store_topology_information
5512 (
5513     nvswitch_device *device,
5514     nvlink_link *link
5515 )
5516 {
5517     return device->hal.nvswitch_store_topology_information(device, link);
5518 }
5519 
5520 void
nvswitch_init_lpwr_regs(nvlink_link * link)5521 nvswitch_init_lpwr_regs
5522 (
5523     nvlink_link *link
5524 )
5525 {
5526    nvswitch_device *device = link->dev->pDevInfo;
5527    device->hal.nvswitch_init_lpwr_regs(link);
5528 }
5529 
5530 void
nvswitch_program_l1_scratch_reg(nvswitch_device * device,NvU32 linkNumber)5531 nvswitch_program_l1_scratch_reg
5532 (
5533     nvswitch_device *device,
5534     NvU32 linkNumber
5535 )
5536 {
5537    device->hal.nvswitch_program_l1_scratch_reg(device, linkNumber);
5538 }
5539 
5540 NvlStatus
nvswitch_check_io_sanity(nvswitch_device * device)5541 nvswitch_check_io_sanity
5542 (
5543     nvswitch_device *device
5544 )
5545 {
5546     return device->hal.nvswitch_check_io_sanity(device);
5547 }
5548 
5549 NvlStatus
nvswitch_launch_ALI(nvswitch_device * device)5550 nvswitch_launch_ALI
5551 (
5552     nvswitch_device *device
5553 )
5554 {
5555     return device->hal.nvswitch_launch_ALI(device);
5556 }
5557 
5558 NvlStatus
nvswitch_set_training_mode(nvswitch_device * device)5559 nvswitch_set_training_mode
5560 (
5561     nvswitch_device *device
5562 )
5563 {
5564     return device->hal.nvswitch_set_training_mode(device);
5565 }
5566 
5567 NvBool
nvswitch_is_link_in_reset(nvswitch_device * device,nvlink_link * link)5568 nvswitch_is_link_in_reset
5569 (
5570     nvswitch_device *device,
5571     nvlink_link     *link
5572 )
5573 {
5574     return device->hal.nvswitch_is_link_in_reset(device, link);
5575 }
5576 
5577 NvBool
nvswitch_i2c_is_device_access_allowed(nvswitch_device * device,NvU32 port,NvU8 addr,NvBool bIsRead)5578 nvswitch_i2c_is_device_access_allowed
5579 (
5580     nvswitch_device *device,
5581     NvU32 port,
5582     NvU8 addr,
5583     NvBool bIsRead
5584 )
5585 {
5586     return device->hal.nvswitch_i2c_is_device_access_allowed(device, port, addr, bIsRead);
5587 }
5588 
5589 NvlStatus
nvswitch_parse_bios_image(nvswitch_device * device)5590 nvswitch_parse_bios_image
5591 (
5592     nvswitch_device *device
5593 )
5594 {
5595     return device->hal.nvswitch_parse_bios_image(device);
5596 }
5597 
5598 void
nvswitch_init_buffer_ready(nvswitch_device * device,nvlink_link * link,NvBool bNportBufferReady)5599 nvswitch_init_buffer_ready
5600 (
5601     nvswitch_device *device,
5602     nvlink_link *link,
5603     NvBool bNportBufferReady
5604 )
5605 {
5606     return device->hal.nvswitch_init_buffer_ready(device, link, bNportBufferReady);
5607 }
5608 
5609 void
nvswitch_apply_recal_settings(nvswitch_device * device,nvlink_link * link)5610 nvswitch_apply_recal_settings
5611 (
5612     nvswitch_device *device,
5613     nvlink_link *link
5614 )
5615 {
5616     return device->hal.nvswitch_apply_recal_settings(device, link);
5617 }
5618 
5619 NvlStatus
nvswitch_launch_ALI_link_training(nvswitch_device * device,nvlink_link * link,NvBool bSync)5620 nvswitch_launch_ALI_link_training
5621 (
5622     nvswitch_device *device,
5623     nvlink_link *link,
5624     NvBool bSync
5625 )
5626 {
5627     return device->hal.nvswitch_launch_ALI_link_training(device, link, bSync);
5628 }
5629 
5630 NvlStatus
nvswitch_reset_and_train_link(nvswitch_device * device,nvlink_link * link)5631 nvswitch_reset_and_train_link
5632 (
5633     nvswitch_device *device,
5634     nvlink_link     *link
5635 )
5636 {
5637     return device->hal.nvswitch_reset_and_train_link(device, link);
5638 }
5639 
5640 static NvlStatus
_nvswitch_ctrl_get_err_info(nvswitch_device * device,NVSWITCH_NVLINK_GET_ERR_INFO_PARAMS * ret)5641 _nvswitch_ctrl_get_err_info
5642 (
5643     nvswitch_device *device,
5644     NVSWITCH_NVLINK_GET_ERR_INFO_PARAMS *ret
5645 )
5646 {
5647     return device->hal.nvswitch_ctrl_get_err_info(device, ret);
5648 }
5649 
5650 static NvlStatus
_nvswitch_ctrl_clear_counters(nvswitch_device * device,NVSWITCH_NVLINK_CLEAR_COUNTERS_PARAMS * ret)5651 _nvswitch_ctrl_clear_counters
5652 (
5653     nvswitch_device *device,
5654     NVSWITCH_NVLINK_CLEAR_COUNTERS_PARAMS *ret
5655 )
5656 {
5657     return device->hal.nvswitch_ctrl_clear_counters(device, ret);
5658 }
5659 
5660 void
nvswitch_setup_link_system_registers(nvswitch_device * device,nvlink_link * link)5661 nvswitch_setup_link_system_registers
5662 (
5663     nvswitch_device *device,
5664     nvlink_link *link
5665 )
5666 {
5667     device->hal.nvswitch_setup_link_system_registers(device, link);
5668 }
5669 
5670 void
nvswitch_load_link_disable_settings(nvswitch_device * device,nvlink_link * link)5671 nvswitch_load_link_disable_settings
5672 (
5673     nvswitch_device *device,
5674     nvlink_link *link
5675 )
5676 {
5677     device->hal.nvswitch_load_link_disable_settings(device, link);
5678 }
5679 
5680 static NvlStatus
_nvswitch_ctrl_set_nvlink_error_threshold(nvswitch_device * device,NVSWITCH_SET_NVLINK_ERROR_THRESHOLD_PARAMS * pParams)5681 _nvswitch_ctrl_set_nvlink_error_threshold
5682 (
5683     nvswitch_device *device,
5684     NVSWITCH_SET_NVLINK_ERROR_THRESHOLD_PARAMS *pParams
5685 )
5686 {
5687     return device->hal.nvswitch_ctrl_set_nvlink_error_threshold(device, pParams);
5688 }
5689 
5690 static NvlStatus
_nvswitch_ctrl_get_nvlink_error_threshold(nvswitch_device * device,NVSWITCH_GET_NVLINK_ERROR_THRESHOLD_PARAMS * pParams)5691 _nvswitch_ctrl_get_nvlink_error_threshold
5692 (
5693     nvswitch_device *device,
5694     NVSWITCH_GET_NVLINK_ERROR_THRESHOLD_PARAMS *pParams
5695 )
5696 {
5697     return device->hal.nvswitch_ctrl_get_nvlink_error_threshold(device, pParams);
5698 }
5699 
5700 static NvlStatus
_nvswitch_ctrl_therm_read_voltage(nvswitch_device * device,NVSWITCH_CTRL_GET_VOLTAGE_PARAMS * info)5701 _nvswitch_ctrl_therm_read_voltage
5702 (
5703     nvswitch_device *device,
5704     NVSWITCH_CTRL_GET_VOLTAGE_PARAMS *info
5705 )
5706 {
5707     return device->hal.nvswitch_ctrl_therm_read_voltage(device, info);
5708 }
5709 
5710 static NvlStatus
_nvswitch_ctrl_therm_read_power(nvswitch_device * device,NVSWITCH_GET_POWER_PARAMS * info)5711 _nvswitch_ctrl_therm_read_power
5712 (
5713     nvswitch_device *device,
5714     NVSWITCH_GET_POWER_PARAMS *info
5715 )
5716 {
5717     return device->hal.nvswitch_ctrl_therm_read_power(device, info);
5718 }
5719 
5720 NvlStatus
nvswitch_get_board_id(nvswitch_device * device,NvU16 * boardId)5721 nvswitch_get_board_id
5722 (
5723     nvswitch_device *device,
5724     NvU16 *boardId
5725 )
5726 {
5727     return device->hal.nvswitch_get_board_id(device, boardId);
5728 }
5729 
5730 NvlStatus
_nvswitch_ctrl_get_link_l1_capability(nvswitch_device * device,NVSWITCH_GET_NVLINK_L1_CAPABILITY_PARAMS * p)5731 _nvswitch_ctrl_get_link_l1_capability
5732 (
5733     nvswitch_device *device,
5734     NVSWITCH_GET_NVLINK_L1_CAPABILITY_PARAMS *p
5735 )
5736 {
5737     NvlStatus status;
5738     nvlink_link *link;
5739     NvU8 i;
5740 
5741     if (p->linkMask == 0)
5742     {
5743         NVSWITCH_PRINT(device, ERROR, "%s: No links in linkMask\n", __FUNCTION__);
5744         return -NVL_BAD_ARGS;
5745     }
5746 
5747     FOR_EACH_INDEX_IN_MASK(64, i, p->linkMask)
5748     {
5749         NvU32 linkNum;
5750 
5751         NVSWITCH_ASSERT(i < NVSWITCH_LINK_COUNT(device));
5752 
5753         link = nvswitch_get_link(device, i);
5754         if ((link == NULL) ||
5755             (i >= NVSWITCH_NVLINK_MAX_LINKS))
5756         {
5757             NVSWITCH_PRINT(device, ERROR, "%s: Invalid input link %d set in linkMask\n",
5758                            __FUNCTION__, i);
5759             return -NVL_BAD_ARGS;
5760         }
5761 
5762         linkNum = link->linkNumber;
5763 
5764         status = device->hal.nvswitch_ctrl_get_link_l1_capability(device, linkNum, &(p->l1Capable[linkNum]));
5765         if (status != NVL_SUCCESS)
5766         {
5767             NVSWITCH_PRINT(device, ERROR, "%s: Failed to get l1 capability for link %d\n",
5768                            __FUNCTION__, linkNum);
5769             return status;
5770         }
5771     }
5772     FOR_EACH_INDEX_IN_MASK_END;
5773 
5774     return NVL_SUCCESS;
5775 }
5776 
5777 NvlStatus
_nvswitch_ctrl_get_link_l1_threshold(nvswitch_device * device,NVSWITCH_GET_NVLINK_L1_THRESHOLD_PARAMS * p)5778 _nvswitch_ctrl_get_link_l1_threshold
5779 (
5780     nvswitch_device *device,
5781     NVSWITCH_GET_NVLINK_L1_THRESHOLD_PARAMS *p
5782 )
5783 {
5784     NvlStatus status;
5785     nvlink_link *link;
5786     NvBool isL1Capable;
5787     NvU8 i;
5788 
5789     if (device->regkeys.enable_pm == NV_SWITCH_REGKEY_ENABLE_PM_NO)
5790     {
5791         NVSWITCH_PRINT(device, INFO, "%s: L1 Threshold is disabled\n", __FUNCTION__);
5792         return -NVL_ERR_NOT_SUPPORTED;
5793     }
5794 
5795     if (p->linkMask == 0)
5796     {
5797         NVSWITCH_PRINT(device, ERROR, "%s: No links in linkMask\n", __FUNCTION__);
5798         return -NVL_BAD_ARGS;
5799     }
5800 
5801     FOR_EACH_INDEX_IN_MASK(64, i, p->linkMask)
5802     {
5803         NvU32 linkNum;
5804 
5805         NVSWITCH_ASSERT(i < NVSWITCH_LINK_COUNT(device));
5806 
5807         link = nvswitch_get_link(device, i);
5808         if ((link == NULL) ||
5809             (i >= NVSWITCH_NVLINK_MAX_LINKS))
5810         {
5811             NVSWITCH_PRINT(device, ERROR, "%s: Invalid input link %d set in linkMask\n",
5812                            __FUNCTION__, i);
5813             return -NVL_BAD_ARGS;
5814         }
5815 
5816         linkNum = link->linkNumber;
5817 
5818         status = device->hal.nvswitch_ctrl_get_link_l1_capability(device, linkNum, &isL1Capable);
5819         if (status != NVL_SUCCESS)
5820         {
5821             NVSWITCH_PRINT(device, ERROR, "%s: Failed to get l1 capability for link %d\n",
5822                            __FUNCTION__, linkNum);
5823             return status;
5824         }
5825 
5826         if (!isL1Capable)
5827         {
5828             NVSWITCH_PRINT(device, ERROR, "%s: Input link %d does not support L1\n",
5829                            __FUNCTION__, i);
5830             return -NVL_ERR_NOT_SUPPORTED;
5831         }
5832 
5833         // Get HAL
5834         status = device->hal.nvswitch_ctrl_get_link_l1_threshold(device, linkNum, &(p->l1Threshold[linkNum]));
5835         if (status != NVL_SUCCESS)
5836         {
5837             NVSWITCH_PRINT(device, ERROR, "%s: Failed to get L1 Threshold for link %d\n",
5838                            __FUNCTION__, linkNum);
5839             return status;
5840         }
5841     }
5842     FOR_EACH_INDEX_IN_MASK_END;
5843 
5844     return NVL_SUCCESS;
5845 }
5846 
5847 NvlStatus
_nvswitch_ctrl_set_link_l1_threshold(nvswitch_device * device,NVSWITCH_SET_NVLINK_L1_THRESHOLD_PARAMS * p)5848 _nvswitch_ctrl_set_link_l1_threshold
5849 (
5850     nvswitch_device *device,
5851     NVSWITCH_SET_NVLINK_L1_THRESHOLD_PARAMS *p
5852 )
5853 {
5854     NvlStatus status;
5855     nvlink_link *link;
5856     NvBool isL1Capable;
5857     NvU8 i;
5858 
5859     if (device->regkeys.enable_pm == NV_SWITCH_REGKEY_ENABLE_PM_NO)
5860     {
5861         NVSWITCH_PRINT(device, INFO, "%s: L1 Threshold is disabled\n", __FUNCTION__);
5862         return -NVL_ERR_NOT_SUPPORTED;
5863     }
5864 
5865     if (p->linkMask == 0)
5866     {
5867         NVSWITCH_PRINT(device, ERROR, "%s: No links in linkMask\n", __FUNCTION__);
5868         return -NVL_BAD_ARGS;
5869     }
5870 
5871     FOR_EACH_INDEX_IN_MASK(64, i, p->linkMask)
5872     {
5873         NvU32 linkNum;
5874         NvU32 l1Threshold;
5875 
5876         NVSWITCH_ASSERT(i < NVSWITCH_LINK_COUNT(device));
5877 
5878         link = nvswitch_get_link(device, i);
5879         if ((link == NULL) ||
5880             (i >= NVSWITCH_NVLINK_MAX_LINKS))
5881         {
5882             NVSWITCH_PRINT(device, ERROR, "%s: Invalid input link %d set in linkMask\n",
5883                            __FUNCTION__, i);
5884             return -NVL_BAD_ARGS;
5885         }
5886 
5887         linkNum = link->linkNumber;
5888         l1Threshold = p->l1Threshold[linkNum];
5889 
5890         status = device->hal.nvswitch_ctrl_get_link_l1_capability(device, linkNum, &isL1Capable);
5891         if (status != NVL_SUCCESS)
5892         {
5893             NVSWITCH_PRINT(device, ERROR, "%s: Failed to get l1 capability for link %d\n",
5894                            __FUNCTION__, linkNum);
5895             return status;
5896         }
5897 
5898         if (!isL1Capable)
5899         {
5900             NVSWITCH_PRINT(device, ERROR, "%s: Input link %d does not support L1\n",
5901                            __FUNCTION__, i);
5902             return -NVL_ERR_NOT_SUPPORTED;
5903         }
5904 
5905         if (((l1Threshold < NVSWITCH_SET_NVLINK_L1_THRESHOLD_MIN) ||
5906              (l1Threshold > NVSWITCH_SET_NVLINK_L1_THRESHOLD_MAX)) &&
5907             (l1Threshold != NVSWITCH_SET_NVLINK_L1_THRESHOLD_DEFAULT))
5908         {
5909             return -NVL_BAD_ARGS;
5910         }
5911 
5912         status = device->hal.nvswitch_ctrl_set_link_l1_threshold(link,
5913                                                                  p->l1Threshold[linkNum]);
5914         if (status != NVL_SUCCESS)
5915         {
5916             NVSWITCH_PRINT(device, ERROR, "%s: Failed to set L1 Threshold for link %d\n",
5917                            __FUNCTION__, linkNum);
5918             return status;
5919         }
5920     }
5921     FOR_EACH_INDEX_IN_MASK_END
5922 
5923     return NVL_SUCCESS;
5924 }
5925 
5926 NvlStatus
nvswitch_detect_tnvl_mode(nvswitch_device * device)5927 nvswitch_detect_tnvl_mode
5928 (
5929     nvswitch_device *device
5930 )
5931 {
5932     return device->hal.nvswitch_detect_tnvl_mode(device);
5933 }
5934 
5935 NvBool
nvswitch_is_tnvl_mode_enabled(nvswitch_device * device)5936 nvswitch_is_tnvl_mode_enabled
5937 (
5938     nvswitch_device *device
5939 )
5940 {
5941     return device->hal.nvswitch_is_tnvl_mode_enabled(device);
5942 }
5943 
5944 NvBool
nvswitch_is_tnvl_mode_locked(nvswitch_device * device)5945 nvswitch_is_tnvl_mode_locked
5946 (
5947     nvswitch_device *device
5948 )
5949 {
5950     return device->hal.nvswitch_is_tnvl_mode_locked(device);
5951 }
5952 
5953 NvBool NV_API_CALL
nvswitch_lib_is_tnvl_enabled(nvswitch_device * device)5954 nvswitch_lib_is_tnvl_enabled
5955 (
5956     nvswitch_device *device
5957 )
5958 {
5959     return nvswitch_is_tnvl_mode_enabled(device);
5960 }
5961 
5962 NvlStatus
nvswitch_tnvl_send_fsp_lock_config(nvswitch_device * device)5963 nvswitch_tnvl_send_fsp_lock_config
5964 (
5965     nvswitch_device *device
5966 )
5967 {
5968     return device->hal.nvswitch_tnvl_send_fsp_lock_config(device);
5969 }
5970 
5971 static NvlStatus
_nvswitch_ctrl_set_device_tnvl_lock(nvswitch_device * device,NVSWITCH_SET_DEVICE_TNVL_LOCK_PARAMS * p)5972 _nvswitch_ctrl_set_device_tnvl_lock
5973 (
5974     nvswitch_device *device,
5975     NVSWITCH_SET_DEVICE_TNVL_LOCK_PARAMS *p
5976 )
5977 {
5978     NvlStatus status = NVL_SUCCESS;
5979 
5980     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
5981     {
5982         return -NVL_BAD_ARGS;
5983     }
5984 
5985     if (!nvswitch_is_tnvl_mode_enabled(device))
5986     {
5987         NVSWITCH_PRINT(device, ERROR,
5988            "%s: TNVL is not enabled\n",
5989            __FUNCTION__);
5990         return -NVL_ERR_NOT_SUPPORTED;
5991     }
5992 
5993     // Return failure if FM is not yet configured
5994     if (device->device_fabric_state != NVSWITCH_DEVICE_FABRIC_STATE_CONFIGURED)
5995     {
5996         NVSWITCH_PRINT(device, ERROR,
5997            "%s: FM is not configured yet\n",
5998            __FUNCTION__);
5999         return -NVL_ERR_INVALID_STATE;
6000     }
6001 
6002     //
6003     // Disable non-fatal and legacy interrupts
6004     // Disable commands to SOE
6005     //
6006 
6007     // Send lock-config command to FSP
6008     status = nvswitch_tnvl_send_fsp_lock_config(device);
6009     if (status == NVL_SUCCESS)
6010     {
6011         device->tnvl_mode = NVSWITCH_DEVICE_TNVL_MODE_LOCKED;
6012     }
6013     else
6014     {
6015         device->tnvl_mode = NVSWITCH_DEVICE_TNVL_MODE_FAILURE;
6016     }
6017 
6018     return status;
6019 }
6020 
6021 NvlStatus
nvswitch_lib_ctrl(nvswitch_device * device,NvU32 cmd,void * params,NvU64 size,void * osPrivate)6022 nvswitch_lib_ctrl
6023 (
6024     nvswitch_device *device,
6025     NvU32 cmd,
6026     void *params,
6027     NvU64 size,
6028     void *osPrivate
6029 )
6030 {
6031     NvlStatus retval;
6032     NvU64 flags = 0;
6033 
6034     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device) || params == NULL)
6035     {
6036         return -NVL_BAD_ARGS;
6037     }
6038 
6039     flags = NVSWITCH_DEV_CMD_CHECK_ADMIN | NVSWITCH_DEV_CMD_CHECK_FM;
6040     switch (cmd)
6041     {
6042         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_INFO,
6043                 _nvswitch_ctrl_get_info,
6044                 NVSWITCH_GET_INFO);
6045         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_INTERNAL_LATENCY,
6046                 _nvswitch_ctrl_get_internal_latency,
6047                 NVSWITCH_GET_INTERNAL_LATENCY);
6048         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_NVLIPT_COUNTERS,
6049                 _nvswitch_ctrl_get_nvlipt_counters,
6050                 NVSWITCH_GET_NVLIPT_COUNTERS);
6051         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_ERRORS,
6052                 nvswitch_ctrl_get_errors,
6053                 NVSWITCH_GET_ERRORS_PARAMS);
6054         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_PORT_EVENTS,
6055                 nvswitch_ctrl_get_port_events,
6056                 NVSWITCH_GET_PORT_EVENTS_PARAMS);
6057         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_NVLINK_STATUS,
6058                 _nvswitch_ctrl_get_nvlink_status,
6059                 NVSWITCH_GET_NVLINK_STATUS_PARAMS);
6060         NVSWITCH_DEV_CMD_DISPATCH_WITH_PRIVATE_DATA(
6061                 CTRL_NVSWITCH_ACQUIRE_CAPABILITY,
6062                 _nvswitch_ctrl_acquire_capability,
6063                 NVSWITCH_ACQUIRE_CAPABILITY_PARAMS,
6064                 osPrivate);
6065         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_TEMPERATURE,
6066                 _nvswitch_ctrl_therm_read_temperature,
6067                 NVSWITCH_CTRL_GET_TEMPERATURE_PARAMS);
6068         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_THROUGHPUT_COUNTERS,
6069                 nvswitch_ctrl_get_throughput_counters,
6070                 NVSWITCH_GET_THROUGHPUT_COUNTERS_PARAMS);
6071         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_FATAL_ERROR_SCOPE,
6072                 _nvswitch_ctrl_get_fatal_error_scope,
6073                 NVSWITCH_GET_FATAL_ERROR_SCOPE_PARAMS);
6074         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6075                 CTRL_NVSWITCH_SET_SWITCH_PORT_CONFIG,
6076                 _nvswitch_ctrl_set_switch_port_config,
6077                 NVSWITCH_SET_SWITCH_PORT_CONFIG,
6078                 osPrivate, flags);
6079         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6080                 CTRL_NVSWITCH_GET_INGRESS_REQUEST_TABLE,
6081                 _nvswitch_ctrl_get_ingress_request_table,
6082                 NVSWITCH_GET_INGRESS_REQUEST_TABLE_PARAMS,
6083                 osPrivate, flags);
6084         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6085                 CTRL_NVSWITCH_SET_INGRESS_REQUEST_TABLE,
6086                 _nvswitch_ctrl_set_ingress_request_table,
6087                 NVSWITCH_SET_INGRESS_REQUEST_TABLE,
6088                 osPrivate, flags);
6089         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6090                 CTRL_NVSWITCH_SET_INGRESS_REQUEST_VALID,
6091                 _nvswitch_ctrl_set_ingress_request_valid,
6092                 NVSWITCH_SET_INGRESS_REQUEST_VALID,
6093                 osPrivate, flags);
6094         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6095                 CTRL_NVSWITCH_GET_INGRESS_RESPONSE_TABLE,
6096                 _nvswitch_ctrl_get_ingress_response_table,
6097                 NVSWITCH_GET_INGRESS_RESPONSE_TABLE_PARAMS,
6098                 osPrivate, flags);
6099         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6100                 CTRL_NVSWITCH_SET_INGRESS_RESPONSE_TABLE,
6101                 _nvswitch_ctrl_set_ingress_response_table,
6102                 NVSWITCH_SET_INGRESS_RESPONSE_TABLE,
6103                 osPrivate, flags);
6104         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6105                 CTRL_NVSWITCH_SET_GANGED_LINK_TABLE,
6106                 _nvswitch_ctrl_set_ganged_link_table,
6107                 NVSWITCH_SET_GANGED_LINK_TABLE,
6108                 osPrivate, flags);
6109         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_LATENCY_BINS,
6110                 nvswitch_ctrl_set_latency_bins,
6111                 NVSWITCH_SET_LATENCY_BINS,
6112                 osPrivate, flags);
6113         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6114                 CTRL_NVSWITCH_SET_NVLIPT_COUNTER_CONFIG,
6115                 _nvswitch_ctrl_set_nvlipt_counter_config,
6116                 NVSWITCH_SET_NVLIPT_COUNTER_CONFIG,
6117                 osPrivate, flags);
6118         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6119                 CTRL_NVSWITCH_GET_NVLIPT_COUNTER_CONFIG,
6120                 _nvswitch_ctrl_get_nvlipt_counter_config,
6121                 NVSWITCH_GET_NVLIPT_COUNTER_CONFIG,
6122                 osPrivate, flags);
6123         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_REMAP_POLICY,
6124                 _nvswitch_ctrl_set_remap_policy,
6125                 NVSWITCH_SET_REMAP_POLICY,
6126                 osPrivate, flags);
6127         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_GET_REMAP_POLICY,
6128                 _nvswitch_ctrl_get_remap_policy,
6129                 NVSWITCH_GET_REMAP_POLICY_PARAMS,
6130                 osPrivate, flags);
6131         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6132                 CTRL_NVSWITCH_SET_REMAP_POLICY_VALID,
6133                 _nvswitch_ctrl_set_remap_policy_valid,
6134                 NVSWITCH_SET_REMAP_POLICY_VALID,
6135                 osPrivate, flags);
6136         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_ROUTING_ID,
6137                 _nvswitch_ctrl_set_routing_id,
6138                 NVSWITCH_SET_ROUTING_ID,
6139                 osPrivate, flags);
6140         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_GET_ROUTING_ID,
6141                 _nvswitch_ctrl_get_routing_id,
6142                 NVSWITCH_GET_ROUTING_ID_PARAMS,
6143                 osPrivate, flags);
6144         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_ROUTING_ID_VALID,
6145                 _nvswitch_ctrl_set_routing_id_valid,
6146                 NVSWITCH_SET_ROUTING_LAN_VALID,
6147                 osPrivate, flags);
6148         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_ROUTING_LAN,
6149                 _nvswitch_ctrl_set_routing_lan,
6150                 NVSWITCH_SET_ROUTING_LAN,
6151                 osPrivate, flags);
6152         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_GET_ROUTING_LAN,
6153                 _nvswitch_ctrl_get_routing_lan,
6154                 NVSWITCH_GET_ROUTING_LAN_PARAMS,
6155                 osPrivate, flags);
6156         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6157                 CTRL_NVSWITCH_SET_ROUTING_LAN_VALID,
6158                 _nvswitch_ctrl_set_routing_lan_valid,
6159                 NVSWITCH_SET_ROUTING_LAN_VALID,
6160                 osPrivate, flags);
6161         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6162                 CTRL_NVSWITCH_GET_INGRESS_REQLINKID,
6163                 _nvswitch_ctrl_get_ingress_reqlinkid,
6164                 NVSWITCH_GET_INGRESS_REQLINKID_PARAMS,
6165                 osPrivate, flags);
6166         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_UNREGISTER_LINK,
6167                 _nvswitch_ctrl_unregister_link,
6168                 NVSWITCH_UNREGISTER_LINK_PARAMS,
6169                 osPrivate, flags);
6170         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6171                 CTRL_NVSWITCH_RESET_AND_DRAIN_LINKS,
6172                 _nvswitch_ctrl_reset_and_drain_links,
6173                 NVSWITCH_RESET_AND_DRAIN_LINKS_PARAMS,
6174                 osPrivate, flags);
6175         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_BIOS_INFO,
6176                 _nvswitch_ctrl_get_bios_info,
6177                 NVSWITCH_GET_BIOS_INFO_PARAMS);
6178         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_INFOROM_VERSION,
6179                 _nvswitch_ctrl_get_inforom_version,
6180                 NVSWITCH_GET_INFOROM_VERSION_PARAMS);
6181         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6182                 CTRL_NVSWITCH_BLACKLIST_DEVICE,
6183                 nvswitch_ctrl_blacklist_device,
6184                 NVSWITCH_BLACKLIST_DEVICE_PARAMS,
6185                 osPrivate, flags);
6186         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6187                 CTRL_NVSWITCH_SET_FM_DRIVER_STATE,
6188                 nvswitch_ctrl_set_fm_driver_state,
6189                 NVSWITCH_SET_FM_DRIVER_STATE_PARAMS,
6190                 osPrivate, flags);
6191         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6192                 CTRL_NVSWITCH_SET_DEVICE_FABRIC_STATE,
6193                 nvswitch_ctrl_set_device_fabric_state,
6194                 NVSWITCH_SET_DEVICE_FABRIC_STATE_PARAMS,
6195                 osPrivate, flags);
6196         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6197                 CTRL_NVSWITCH_SET_FM_HEARTBEAT_TIMEOUT,
6198                 nvswitch_ctrl_set_fm_timeout,
6199                 NVSWITCH_SET_FM_HEARTBEAT_TIMEOUT_PARAMS,
6200                 osPrivate, flags);
6201         NVSWITCH_DEV_CMD_DISPATCH_WITH_PRIVATE_DATA(
6202                 CTRL_NVSWITCH_REGISTER_EVENTS,
6203                 _nvswitch_ctrl_register_events,
6204                 NVSWITCH_REGISTER_EVENTS_PARAMS,
6205                 osPrivate);
6206         NVSWITCH_DEV_CMD_DISPATCH_WITH_PRIVATE_DATA(
6207                 CTRL_NVSWITCH_UNREGISTER_EVENTS,
6208                 _nvswitch_ctrl_unregister_events,
6209                 NVSWITCH_UNREGISTER_EVENTS_PARAMS,
6210                 osPrivate);
6211         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6212                 CTRL_NVSWITCH_SET_TRAINING_ERROR_INFO,
6213                 _nvswitch_ctrl_set_training_error_info,
6214                 NVSWITCH_SET_TRAINING_ERROR_INFO_PARAMS,
6215                 osPrivate, flags);
6216         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6217                 CTRL_NVSWITCH_SET_MC_RID_TABLE,
6218                 _nvswitch_ctrl_set_mc_rid_table,
6219                 NVSWITCH_SET_MC_RID_TABLE_PARAMS,
6220                 osPrivate, flags);
6221         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6222                 CTRL_NVSWITCH_GET_MC_RID_TABLE,
6223                 _nvswitch_ctrl_get_mc_rid_table,
6224                 NVSWITCH_GET_MC_RID_TABLE_PARAMS,
6225                 osPrivate, flags);
6226         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6227                 CTRL_NVSWITCH_GET_COUNTERS,
6228                 _nvswitch_ctrl_get_counters,
6229                 NVSWITCH_NVLINK_GET_COUNTERS_PARAMS,
6230                 osPrivate, flags);
6231         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6232                 CTRL_NVSWITCH_GET_NVLINK_ECC_ERRORS,
6233                 _nvswitch_ctrl_get_nvlink_ecc_errors,
6234                 NVSWITCH_GET_NVLINK_ECC_ERRORS_PARAMS,
6235                 osPrivate, flags);
6236         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6237                 CTRL_NVSWITCH_I2C_SMBUS_COMMAND,
6238                 _nvswitch_ctrl_i2c_smbus_command,
6239                 NVSWITCH_I2C_SMBUS_COMMAND_PARAMS,
6240                 osPrivate, NVSWITCH_DEV_CMD_CHECK_ADMIN);
6241         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6242                 CTRL_NVSWITCH_CCI_CMIS_PRESENCE,
6243                 _nvswitch_ctrl_cci_cmis_presence,
6244                 NVSWITCH_CCI_CMIS_PRESENCE_PARAMS,
6245                 osPrivate, flags);
6246         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6247                 CTRL_NVSWITCH_CCI_CMIS_NVLINK_MAPPING,
6248                 _nvswitch_ctrl_cci_nvlink_mappings,
6249                 NVSWITCH_CCI_CMIS_NVLINK_MAPPING_PARAMS,
6250                 osPrivate, flags);
6251         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6252                 CTRL_NVSWITCH_CCI_CMIS_MEMORY_ACCESS_READ,
6253                 _nvswitch_ctrl_cci_memory_access_read,
6254                 NVSWITCH_CCI_CMIS_MEMORY_ACCESS_READ_PARAMS,
6255                 osPrivate, flags);
6256         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6257                 CTRL_NVSWITCH_CCI_CMIS_MEMORY_ACCESS_WRITE,
6258                 _nvswitch_ctrl_cci_memory_access_write,
6259                 NVSWITCH_CCI_CMIS_MEMORY_ACCESS_WRITE_PARAMS,
6260                 osPrivate, flags);
6261         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6262                 CTRL_NVSWITCH_CCI_CMIS_CAGE_BEZEL_MARKING,
6263                 _nvswitch_ctrl_cci_cage_bezel_marking,
6264                 NVSWITCH_CCI_CMIS_CAGE_BEZEL_MARKING_PARAMS,
6265                 osPrivate, flags);
6266         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6267                 CTRL_NVSWITCH_CCI_GET_GRADING_VALUES,
6268                 nvswitch_ctrl_get_grading_values,
6269                 NVSWITCH_CCI_GET_GRADING_VALUES_PARAMS,
6270                 osPrivate, flags);
6271         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6272                 CTRL_NVSWITCH_CCI_GET_PORTS_CPLD_INFO,
6273                 nvswitch_ctrl_get_ports_cpld_info,
6274                 NVSWITCH_CCI_GET_PORTS_CPLD_INFO_PARAMS,
6275                 osPrivate, flags);
6276         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6277                 CTRL_NVSWITCH_CCI_GET_FW_REVISIONS,
6278                 nvswitch_ctrl_get_cci_fw_revisions,
6279                 NVSWITCH_CCI_GET_FW_REVISION_PARAMS,
6280                 osPrivate, flags);
6281         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6282                 CTRL_NVSWITCH_CCI_SET_LOCATE_LED,
6283                 nvswitch_ctrl_set_locate_led,
6284                 NVSWITCH_CCI_SET_LOCATE_LED_PARAMS,
6285                 osPrivate, flags);
6286         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6287                 CTRL_NVSWITCH_GET_SOE_HEARTBEAT,
6288                 _nvswitch_ctrl_get_soe_heartbeat,
6289                 NVSWITCH_GET_SOE_HEARTBEAT_PARAMS,
6290                 osPrivate, flags);
6291         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6292                 CTRL_NVSWITCH_SET_CONTINUOUS_ALI,
6293                 _nvswitch_ctrl_set_continuous_ali,
6294                 NVSWITCH_SET_CONTINUOUS_ALI_PARAMS,
6295                 osPrivate, flags);
6296         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6297                 CTRL_NVSWITCH_REQUEST_ALI,
6298                 _nvswitch_ctrl_request_ali,
6299                 NVSWITCH_REQUEST_ALI_PARAMS,
6300                 osPrivate, flags);
6301         NVSWITCH_DEV_CMD_DISPATCH(
6302                 CTRL_NVSWITCH_GET_TEMPERATURE_LIMIT,
6303                 _nvswitch_ctrl_therm_get_temperature_limit,
6304                 NVSWITCH_CTRL_GET_TEMPERATURE_LIMIT_PARAMS);
6305         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6306                 CTRL_NVSWITCH_GET_NVLINK_MAX_ERROR_RATES,
6307                 _nvswitch_ctrl_get_inforom_nvlink_max_correctable_error_rate,
6308                 NVSWITCH_GET_NVLINK_MAX_CORRECTABLE_ERROR_RATES_PARAMS,
6309                 osPrivate, flags);
6310         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6311                 CTRL_NVSWITCH_GET_NVLINK_ERROR_COUNTS,
6312                 _nvswitch_ctrl_get_inforom_nvlink_errors,
6313                 NVSWITCH_GET_NVLINK_ERROR_COUNTS_PARAMS,
6314                 osPrivate, flags);
6315         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6316                 CTRL_NVSWITCH_GET_ECC_ERROR_COUNTS,
6317                 _nvswitch_ctrl_get_inforom_ecc_errors,
6318                 NVSWITCH_GET_ECC_ERROR_COUNTS_PARAMS,
6319                 osPrivate, flags);
6320         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6321                 CTRL_NVSWITCH_GET_SXIDS,
6322                 _nvswitch_ctrl_get_inforom_bbx_sxid,
6323                 NVSWITCH_GET_SXIDS_PARAMS,
6324                 osPrivate, flags);
6325         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6326                 CTRL_NVSWITCH_GET_FOM_VALUES,
6327                 _nvswitch_ctrl_get_fom_values,
6328                 NVSWITCH_GET_FOM_VALUES_PARAMS,
6329                 osPrivate, flags);
6330         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6331                 CTRL_NVSWITCH_GET_NVLINK_LP_COUNTERS,
6332                 _nvswitch_ctrl_get_nvlink_lp_counters,
6333                 NVSWITCH_GET_NVLINK_LP_COUNTERS_PARAMS,
6334                 osPrivate, flags);
6335         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_RESIDENCY_BINS,
6336                 _nvswitch_ctrl_get_residency_bins,
6337                 NVSWITCH_GET_RESIDENCY_BINS);
6338         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_RESIDENCY_BINS,
6339                 _nvswitch_ctrl_set_residency_bins,
6340                 NVSWITCH_SET_RESIDENCY_BINS,
6341                 osPrivate, flags);
6342         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_RB_STALL_BUSY,
6343                 _nvswitch_ctrl_get_rb_stall_busy,
6344                 NVSWITCH_GET_RB_STALL_BUSY);
6345         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_MULTICAST_ID_ERROR_VECTOR,
6346                 nvswitch_ctrl_get_multicast_id_error_vector,
6347                 NVSWITCH_GET_MULTICAST_ID_ERROR_VECTOR);
6348         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_CLEAR_MULTICAST_ID_ERROR_VECTOR,
6349                 nvswitch_ctrl_clear_multicast_id_error_vector,
6350                 NVSWITCH_CLEAR_MULTICAST_ID_ERROR_VECTOR);
6351         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6352                 CTRL_NVSWITCH_INBAND_SEND_DATA,
6353                 _nvswitch_ctrl_inband_send_data,
6354                 NVSWITCH_INBAND_SEND_DATA_PARAMS,
6355                 osPrivate, flags);
6356         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6357                 CTRL_NVSWITCH_INBAND_READ_DATA,
6358                 _nvswitch_ctrl_inband_read_data,
6359                  NVSWITCH_INBAND_READ_DATA_PARAMS,
6360                 osPrivate, flags);
6361         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6362                 CTRL_NVSWITCH_INBAND_FLUSH_DATA,
6363                 _nvswitch_ctrl_inband_flush_data,
6364                 NVSWITCH_INBAND_FLUSH_DATA_PARAMS,
6365                 osPrivate, flags);
6366         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6367                 CTRL_NVSWITCH_INBAND_PENDING_DATA_STATS,
6368                 _nvswitch_ctrl_inband_pending_data_stats,
6369                 NVSWITCH_INBAND_PENDING_DATA_STATS_PARAMS,
6370                 osPrivate, flags);
6371         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_BOARD_PART_NUMBER,
6372                 _nvswitch_ctrl_get_board_part_number,
6373                 NVSWITCH_GET_BOARD_PART_NUMBER_VECTOR);
6374         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6375                 CTRL_NVSWITCH_GET_SW_INFO,
6376                 _nvswitch_ctrl_get_sw_info,
6377                 NVSWITCH_GET_SW_INFO_PARAMS,
6378                 osPrivate, flags);
6379         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_REGISTER_READ,
6380                 _nvswitch_ctrl_register_read,
6381                 NVSWITCH_REGISTER_READ,
6382                 osPrivate, flags);
6383         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_REGISTER_WRITE,
6384                 _nvswitch_ctrl_register_write,
6385                 NVSWITCH_REGISTER_WRITE,
6386                 osPrivate, flags);
6387         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_GET_ERR_INFO,
6388                 _nvswitch_ctrl_get_err_info,
6389                 NVSWITCH_NVLINK_GET_ERR_INFO_PARAMS,
6390                 osPrivate, flags);
6391         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_CLEAR_COUNTERS,
6392                 _nvswitch_ctrl_clear_counters,
6393                 NVSWITCH_NVLINK_CLEAR_COUNTERS_PARAMS,
6394                 osPrivate, flags);
6395         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_NVLINK_ERROR_THRESHOLD,
6396                 _nvswitch_ctrl_set_nvlink_error_threshold,
6397                 NVSWITCH_SET_NVLINK_ERROR_THRESHOLD_PARAMS,
6398                 osPrivate, flags);
6399         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_NVLINK_ERROR_THRESHOLD,
6400                 _nvswitch_ctrl_get_nvlink_error_threshold,
6401                 NVSWITCH_GET_NVLINK_ERROR_THRESHOLD_PARAMS);
6402         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_VOLTAGE,
6403                 _nvswitch_ctrl_therm_read_voltage,
6404                 NVSWITCH_CTRL_GET_VOLTAGE_PARAMS);
6405         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_POWER,
6406                 _nvswitch_ctrl_therm_read_power,
6407                 NVSWITCH_GET_POWER_PARAMS);
6408         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6409                 CTRL_NVSWITCH_GET_SYS_INFO,
6410                 _nvswitch_ctrl_get_inforom_bbx_sys_info,
6411                 NVSWITCH_GET_SYS_INFO_PARAMS,
6412                 osPrivate, flags);
6413         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6414                 CTRL_NVSWITCH_GET_TIME_INFO,
6415                 _nvswitch_ctrl_get_inforom_bbx_time_info,
6416                 NVSWITCH_GET_TIME_INFO_PARAMS,
6417                 osPrivate, flags);
6418         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6419                 CTRL_NVSWITCH_GET_TEMP_DATA,
6420                 _nvswitch_ctrl_get_inforom_bbx_temp_data,
6421                 NVSWITCH_GET_TEMP_DATA_PARAMS,
6422                 osPrivate, flags);
6423         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6424                 CTRL_NVSWITCH_GET_TEMP_SAMPLES,
6425                 _nvswitch_ctrl_get_inforom_bbx_temp_samples,
6426                 NVSWITCH_GET_TEMP_SAMPLES_PARAMS,
6427                 osPrivate, flags);
6428         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_NVLINK_L1_CAPABILITY,
6429                 _nvswitch_ctrl_get_link_l1_capability,
6430                 NVSWITCH_GET_NVLINK_L1_CAPABILITY_PARAMS);
6431         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_NVLINK_L1_THRESHOLD,
6432                 _nvswitch_ctrl_get_link_l1_threshold,
6433                 NVSWITCH_GET_NVLINK_L1_THRESHOLD_PARAMS);
6434         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_NVLINK_L1_THRESHOLD,
6435                 _nvswitch_ctrl_set_link_l1_threshold,
6436                 NVSWITCH_SET_NVLINK_L1_THRESHOLD_PARAMS,
6437                 osPrivate, flags);
6438         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_FSPRPC_GET_CAPS,
6439                 _nvswitch_ctrl_fsprpc_get_caps,
6440                 NVSWITCH_FSPRPC_GET_CAPS_PARAMS);
6441         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6442                 CTRL_NVSWITCH_SET_DEVICE_TNVL_LOCK,
6443                 _nvswitch_ctrl_set_device_tnvl_lock,
6444                 NVSWITCH_SET_DEVICE_TNVL_LOCK_PARAMS,
6445                 osPrivate, flags);
6446         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6447                 CTRL_NVSWITCH_GET_ATTESTATION_CERTIFICATE_CHAIN,
6448                 _nvswitch_ctrl_get_attestation_certificate_chain,
6449                 NVSWITCH_GET_ATTESTATION_CERTIFICATE_CHAIN_PARAMS,
6450                 osPrivate, flags);
6451         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6452                 CTRL_NVSWITCH_GET_ATTESTATION_REPORT,
6453                 _nvswitch_ctrl_get_attestation_report,
6454                 NVSWITCH_GET_ATTESTATION_REPORT_PARAMS,
6455                 osPrivate, flags);
6456         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
6457                 CTRL_NVSWITCH_GET_TNVL_STATUS,
6458                 _nvswitch_ctrl_get_tnvl_status,
6459                 NVSWITCH_GET_TNVL_STATUS_PARAMS,
6460                 osPrivate, flags);
6461         default:
6462             nvswitch_os_print(NVSWITCH_DBG_LEVEL_INFO, "unknown ioctl %x\n", cmd);
6463             retval = -NVL_BAD_ARGS;
6464             break;
6465     }
6466 
6467     return retval;
6468 }
6469 
6470 #if defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS)
nvswitch_assert_log(const char * function,const char * file,NvU32 line)6471 void nvswitch_assert_log
6472 (
6473     const char *function,
6474     const char *file,
6475     NvU32 line
6476 )
6477 {
6478     nvswitch_os_assert_log("NVSwitch: Assertion failed in %s() at %s:%d\n",
6479                            function, file, line);
6480 }
6481 #else
nvswitch_assert_log(void)6482 void nvswitch_assert_log(void)
6483 {
6484     nvswitch_os_assert_log("NVSwitch: Assertion failed\n");
6485 }
6486 #endif
6487