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 "nvVer.h"
34 #include "nvlink_inband_msg.h"
35 
36 static NvlStatus _nvswitch_ctrl_inband_flush_data(nvswitch_device *device, NVSWITCH_INBAND_FLUSH_DATA_PARAMS *p);
37 
38 #define NVSWITCH_DEV_CMD_CHECK_ADMIN    NVBIT64(0)
39 #define NVSWITCH_DEV_CMD_CHECK_FM       NVBIT64(1)
40 
41 #define NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(cmd, function, type, private, flags)\
42     case cmd:                                                                    \
43     {                                                                            \
44         if (sizeof(type) != size)                                                \
45         {                                                                        \
46             retval = -NVL_BAD_ARGS;                                              \
47             break;                                                               \
48         }                                                                        \
49                                                                                  \
50         retval = _nvswitch_lib_validate_privileged_ctrl(private, flags);         \
51         if (retval != NVL_SUCCESS)                                               \
52         {                                                                        \
53             break;                                                               \
54         }                                                                        \
55                                                                                  \
56         retval = function(device, params);                                       \
57         break;                                                                   \
58     }                                                                            \
59 
60 #define NVSWITCH_DEV_CMD_DISPATCH_RESERVED(cmd)                                  \
61     case cmd:                                                                    \
62     {                                                                            \
63         retval = -NVL_ERR_NOT_IMPLEMENTED;                                       \
64         break;                                                                   \
65     }                                                                            \
66 
67 const static NvU32 nvswitch_lr10_device_ids[] =
68 {
69     0x1AE8, 0x1AF0, 0x1AF1, 0x1AF2, 0x1AF3, 0x1AF4, 0x1AF5, 0x1AF6, 0x1AF7,
70     0x1AF8, 0x1AF9, 0x1AFA, 0x1AFB, 0x1AFC, 0x1AFD, 0x1AFE, 0x1AFF
71 };
72 
73 const static NvU32 nvswitch_ls10_device_ids[] =
74 {
75     // PCIE endpoint to manage the NVLink switch HW
76     0x22A0, 0x22A1, 0x22A2, 0x22A3, 0x22A4, 0x22A5, 0x22A6, 0x22A7,
77     // PCI-PCI Bridge, Laguna Switch Function 0
78     0x22A8, 0x22A9, 0x22AA, 0x22AB,
79     // Non-Transparent Bridge, Laguna Switch Function 1
80     0x22AC, 0x22AD, 0x22AE, 0x22AF
81 };
82 
83 nvlink_link_handlers link_handlers;
84 
85 static NvBool
86 _nvswitch_is_device_id_present
87 (
88     const NvU32 *array,
89     NvU32 array_len,
90     NvU32 device_id
91 )
92 {
93     NvU32 i = 0;
94 
95     for(i = 0; i < array_len; i++)
96     {
97         if (array[i] == device_id)
98         {
99             return NV_TRUE;
100         }
101     }
102 
103     return NV_FALSE;
104 }
105 
106 NvBool
107 nvswitch_is_lr10_device_id
108 (
109     NvU32 device_id
110 )
111 {
112     NvU32 count = (sizeof(nvswitch_lr10_device_ids) /
113                         sizeof(nvswitch_lr10_device_ids[0]));
114 
115     return _nvswitch_is_device_id_present(nvswitch_lr10_device_ids, count, device_id);
116 }
117 
118 NvBool
119 nvswitch_is_ls10_device_id
120 (
121     NvU32 device_id
122 )
123 {
124     NvU32 count = (sizeof(nvswitch_ls10_device_ids) /
125                         sizeof(nvswitch_ls10_device_ids[0]));
126 
127     return _nvswitch_is_device_id_present(nvswitch_ls10_device_ids, count, device_id);
128 }
129 
130 /*
131  * NVLink corelib callbacks are used by the NVLink library separate from the
132  * NVSwitch driver, therefore they do not take a device lock and can not modify
133  * nvswitch_device state or use error logging.
134  *
135  * These NVSwitch functions modify link state outside of the corelib:
136  *   _nvswitch_ctrl_inject_link_error - injects asynchronous link errors (MODS-only)
137  */
138 
139 static NV_API_CALL NvlStatus
140 _nvswitch_corelib_add_link
141 (
142     nvlink_link *link
143 )
144 {
145     nvswitch_device *device = link->dev->pDevInfo;
146     return device->hal.nvswitch_corelib_add_link(link);
147 }
148 
149 static NV_API_CALL NvlStatus
150 _nvswitch_corelib_remove_link
151 (
152     nvlink_link *link
153 )
154 {
155     nvswitch_device *device = link->dev->pDevInfo;
156     return device->hal.nvswitch_corelib_remove_link(link);
157 }
158 
159 static NV_API_CALL NvlStatus
160 _nvswitch_corelib_set_dl_link_mode
161 (
162     nvlink_link *link,
163     NvU64 mode,
164     NvU32 flags
165 )
166 {
167     nvswitch_device *device = link->dev->pDevInfo;
168     return device->hal.nvswitch_corelib_set_dl_link_mode(link, mode, flags);
169 }
170 
171 static NV_API_CALL NvlStatus
172 _nvswitch_corelib_get_dl_link_mode
173 (
174     nvlink_link *link,
175     NvU64 *mode
176 )
177 {
178     nvswitch_device *device = link->dev->pDevInfo;
179     return device->hal.nvswitch_corelib_get_dl_link_mode(link, mode);
180 }
181 
182 static NV_API_CALL NvlStatus
183 _nvswitch_corelib_set_tl_link_mode
184 (
185     nvlink_link *link,
186     NvU64 mode,
187     NvU32 flags
188 )
189 {
190     nvswitch_device *device = link->dev->pDevInfo;
191     return device->hal.nvswitch_corelib_set_tl_link_mode(link, mode, flags);
192 }
193 
194 static NV_API_CALL NvlStatus
195 _nvswitch_corelib_get_tl_link_mode
196 (
197     nvlink_link *link,
198     NvU64 *mode
199 )
200 {
201     nvswitch_device *device = link->dev->pDevInfo;
202     return device->hal.nvswitch_corelib_get_tl_link_mode(link, mode);
203 }
204 
205 static NV_API_CALL NvlStatus
206 _nvswitch_corelib_set_tx_mode
207 (
208     nvlink_link *link,
209     NvU64 mode,
210     NvU32 flags
211 )
212 {
213     nvswitch_device *device = link->dev->pDevInfo;
214     return device->hal.nvswitch_corelib_set_tx_mode(link, mode, flags);
215 }
216 
217 static NV_API_CALL NvlStatus
218 _nvswitch_corelib_get_tx_mode
219 (
220     nvlink_link *link,
221     NvU64 *mode,
222     NvU32 *subMode
223 )
224 {
225     nvswitch_device *device = link->dev->pDevInfo;
226     return device->hal.nvswitch_corelib_get_tx_mode(link, mode, subMode);
227 }
228 
229 static NV_API_CALL NvlStatus
230 _nvswitch_corelib_set_rx_mode
231 (
232     nvlink_link *link,
233     NvU64 mode,
234     NvU32 flags
235 )
236 {
237     nvswitch_device *device = link->dev->pDevInfo;
238     return device->hal.nvswitch_corelib_set_rx_mode(link, mode, flags);
239 }
240 
241 static NV_API_CALL NvlStatus
242 _nvswitch_corelib_get_rx_mode
243 (
244     nvlink_link *link,
245     NvU64 *mode,
246     NvU32 *subMode
247 )
248 {
249     nvswitch_device *device = link->dev->pDevInfo;
250     return device->hal.nvswitch_corelib_get_rx_mode(link, mode, subMode);
251 }
252 
253 static NV_API_CALL NvlStatus
254 _nvswitch_corelib_set_rx_detect
255 (
256     nvlink_link *link,
257     NvU32 flags
258 )
259 {
260     nvswitch_device *device = link->dev->pDevInfo;
261     return device->hal.nvswitch_corelib_set_rx_detect(link, flags);
262 }
263 
264 static NV_API_CALL NvlStatus
265 _nvswitch_corelib_get_rx_detect
266 (
267     nvlink_link *link
268 )
269 {
270     nvswitch_device *device = link->dev->pDevInfo;
271     return device->hal.nvswitch_corelib_get_rx_detect(link);
272 }
273 
274 static NV_API_CALL void
275 _nvswitch_corelib_training_complete
276 (
277     nvlink_link *link
278 )
279 {
280     nvswitch_device *device = link->dev->pDevInfo;
281     device->hal.nvswitch_corelib_training_complete(link);
282 }
283 
284 static NV_API_CALL void
285 _nvswitch_corelib_get_uphy_load
286 (
287     nvlink_link *link,
288     NvBool *bUnlocked
289 )
290 {
291     nvswitch_device *device = link->dev->pDevInfo;
292     return device->hal.nvswitch_corelib_get_uphy_load(link, bUnlocked);
293 }
294 
295 
296 static NV_API_CALL NvlStatus
297 _nvswitch_corelib_write_discovery_token
298 (
299     nvlink_link *link,
300     NvU64 token
301 )
302 {
303     nvswitch_device *device = link->dev->pDevInfo;
304 
305     if (link->version >= NVLINK_DEVICE_VERSION_40)
306     {
307         nvswitch_store_topology_information(device, link);
308         return NVL_SUCCESS;
309     }
310 
311     return NVL_SUCCESS;
312 }
313 
314 static NV_API_CALL NvlStatus
315 _nvswitch_corelib_ali_training
316 (
317     nvlink_link *link
318 )
319 {
320     nvswitch_device *device = link->dev->pDevInfo;
321     return device->hal.nvswitch_launch_ALI_link_training(device, link, NV_FALSE);
322 }
323 
324 void
325 nvswitch_get_link_handlers
326 (
327     nvlink_link_handlers *nvswitch_link_handlers
328 )
329 {
330     if (!nvswitch_link_handlers)
331     {
332         NVSWITCH_ASSERT(0);
333         return;
334     }
335 
336     nvswitch_link_handlers->add = _nvswitch_corelib_add_link;
337     nvswitch_link_handlers->remove = _nvswitch_corelib_remove_link;
338     nvswitch_link_handlers->set_dl_link_mode = _nvswitch_corelib_set_dl_link_mode;
339     nvswitch_link_handlers->get_dl_link_mode = _nvswitch_corelib_get_dl_link_mode;
340     nvswitch_link_handlers->set_tl_link_mode = _nvswitch_corelib_set_tl_link_mode;
341     nvswitch_link_handlers->get_tl_link_mode = _nvswitch_corelib_get_tl_link_mode;
342     nvswitch_link_handlers->set_tx_mode = _nvswitch_corelib_set_tx_mode;
343     nvswitch_link_handlers->get_tx_mode = _nvswitch_corelib_get_tx_mode;
344     nvswitch_link_handlers->set_rx_mode = _nvswitch_corelib_set_rx_mode;
345     nvswitch_link_handlers->get_rx_mode = _nvswitch_corelib_get_rx_mode;
346     nvswitch_link_handlers->set_rx_detect = _nvswitch_corelib_set_rx_detect;
347     nvswitch_link_handlers->get_rx_detect = _nvswitch_corelib_get_rx_detect;
348     nvswitch_link_handlers->training_complete = _nvswitch_corelib_training_complete;
349     nvswitch_link_handlers->get_uphy_load = _nvswitch_corelib_get_uphy_load;
350     nvswitch_link_handlers->write_discovery_token = _nvswitch_corelib_write_discovery_token;
351     nvswitch_link_handlers->ali_training = _nvswitch_corelib_ali_training;
352 }
353 
354 #define NVSWITCH_INIT_REGKEY(_private, _regkey, _string, _default_val)          \
355 do                                                                              \
356 {                                                                               \
357     NvU32 data;                                                                 \
358                                                                                 \
359     device->regkeys._regkey = _default_val;                                     \
360     if (NV_SWITCH_REGKEY_PRIVATE_ALLOWED || !NV_SWITCH_REGKEY##_private)        \
361     {                                                                           \
362         if (NVL_SUCCESS ==                                                      \
363             nvswitch_os_read_registry_dword(device->os_handle, _string, &data)) \
364         {                                                                       \
365             NVSWITCH_PRINT(device, SETUP,                                       \
366                 "%s: Applying regkey %s=0x%x\n",                                \
367                 __FUNCTION__,                                                   \
368                 _string, data);                                                 \
369             device->regkeys._regkey = data;                                     \
370         }                                                                       \
371     }                                                                           \
372 } while(0)
373 
374 static void
375 _nvswitch_init_device_regkeys
376 (
377     nvswitch_device *device
378 )
379 {
380     //
381     // Public external use regkeys
382     //
383     NVSWITCH_INIT_REGKEY(_PUBLIC, ato_control,
384                          NV_SWITCH_REGKEY_ATO_CONTROL,
385                          NV_SWITCH_REGKEY_ATO_CONTROL_DEFAULT);
386 
387     NVSWITCH_INIT_REGKEY(_PUBLIC, sto_control,
388                          NV_SWITCH_REGKEY_STO_CONTROL,
389                          NV_SWITCH_REGKEY_STO_CONTROL_DEFAULT);
390 
391     NVSWITCH_INIT_REGKEY(_PUBLIC, crc_bit_error_rate_short,
392                          NV_SWITCH_REGKEY_CRC_BIT_ERROR_RATE_SHORT,
393                          NV_SWITCH_REGKEY_CRC_BIT_ERROR_RATE_SHORT_DEFAULT);
394 
395     NVSWITCH_INIT_REGKEY(_PUBLIC, crc_bit_error_rate_long,
396                          NV_SWITCH_REGKEY_CRC_BIT_ERROR_RATE_LONG,
397                          NV_SWITCH_REGKEY_CRC_BIT_ERROR_RATE_LONG_DEFAULT);
398 
399     NVSWITCH_INIT_REGKEY(_PUBLIC, surpress_link_errors_for_gpu_reset,
400                          NV_SWITCH_REGKEY_SURPRESS_LINK_ERRORS_FOR_GPU_RESET,
401                          NV_SWITCH_REGKEY_SURPRESS_LINK_ERRORS_FOR_GPU_RESET_DISABLE);
402 
403     //
404     // Debug use regkeys
405     // Not available on release build kernel drivers
406     //
407     NVSWITCH_INIT_REGKEY(_PRIVATE, external_fabric_mgmt,
408                          NV_SWITCH_REGKEY_EXTERNAL_FABRIC_MGMT,
409                          NV_SWITCH_REGKEY_EXTERNAL_FABRIC_MGMT_ENABLE);
410 
411     NVSWITCH_INIT_REGKEY(_PRIVATE, txtrain_control,
412                          NV_SWITCH_REGKEY_TXTRAIN_CONTROL,
413                          NV_SWITCH_REGKEY_TXTRAIN_CONTROL_NOP);
414 
415     NVSWITCH_INIT_REGKEY(_PRIVATE, crossbar_DBI,
416                          NV_SWITCH_REGKEY_CROSSBAR_DBI,
417                          NV_SWITCH_REGKEY_CROSSBAR_DBI_ENABLE);
418 
419     NVSWITCH_INIT_REGKEY(_PRIVATE, link_DBI,
420                          NV_SWITCH_REGKEY_LINK_DBI,
421                          NV_SWITCH_REGKEY_LINK_DBI_ENABLE);
422 
423     NVSWITCH_INIT_REGKEY(_PRIVATE, ac_coupled_mask,
424                          NV_SWITCH_REGKEY_AC_COUPLED_MASK,
425                          0);
426 
427     NVSWITCH_INIT_REGKEY(_PRIVATE, ac_coupled_mask2,
428                          NV_SWITCH_REGKEY_AC_COUPLED_MASK2,
429                          0);
430 
431     NVSWITCH_INIT_REGKEY(_PRIVATE, swap_clk,
432                          NV_SWITCH_REGKEY_SWAP_CLK_OVERRIDE,
433                          nvswitch_get_swap_clk_default(device));
434 
435     NVSWITCH_INIT_REGKEY(_PRIVATE, link_enable_mask,
436                          NV_SWITCH_REGKEY_ENABLE_LINK_MASK,
437                          NV_U32_MAX);
438 
439     NVSWITCH_INIT_REGKEY(_PRIVATE, link_enable_mask2,
440                          NV_SWITCH_REGKEY_ENABLE_LINK_MASK2,
441                          NV_U32_MAX);
442 
443     NVSWITCH_INIT_REGKEY(_PRIVATE, bandwidth_shaper,
444                          NV_SWITCH_REGKEY_BANDWIDTH_SHAPER,
445                          NV_SWITCH_REGKEY_BANDWIDTH_SHAPER_PROD);
446 
447     NVSWITCH_INIT_REGKEY(_PRIVATE, ssg_control,
448                          NV_SWITCH_REGKEY_SSG_CONTROL,
449                          0);
450 
451     NVSWITCH_INIT_REGKEY(_PRIVATE, skip_buffer_ready,
452                          NV_SWITCH_REGKEY_SKIP_BUFFER_READY,
453                          0);
454 
455     NVSWITCH_INIT_REGKEY(_PRIVATE, enable_pm,
456                          NV_SWITCH_REGKEY_ENABLE_PM,
457                          NV_SWITCH_REGKEY_ENABLE_PM_YES);
458 
459     NVSWITCH_INIT_REGKEY(_PRIVATE, chiplib_forced_config_link_mask,
460                          NV_SWITCH_REGKEY_CHIPLIB_FORCED_LINK_CONFIG_MASK,
461                          0);
462 
463     NVSWITCH_INIT_REGKEY(_PRIVATE, chiplib_forced_config_link_mask2,
464                          NV_SWITCH_REGKEY_CHIPLIB_FORCED_LINK_CONFIG_MASK2,
465                          0);
466 
467     NVSWITCH_INIT_REGKEY(_PRIVATE, soe_dma_self_test,
468                          NV_SWITCH_REGKEY_SOE_DMA_SELFTEST,
469                          NV_SWITCH_REGKEY_SOE_DMA_SELFTEST_ENABLE);
470 
471     NVSWITCH_INIT_REGKEY(_PRIVATE, soe_disable,
472                          NV_SWITCH_REGKEY_SOE_DISABLE,
473                          NV_SWITCH_REGKEY_SOE_DISABLE_NO);
474 
475     NVSWITCH_INIT_REGKEY(_PRIVATE, latency_counter,
476                          NV_SWITCH_REGKEY_LATENCY_COUNTER_LOGGING,
477                          NV_SWITCH_REGKEY_LATENCY_COUNTER_LOGGING_ENABLE);
478 
479     NVSWITCH_INIT_REGKEY(_PRIVATE, nvlink_speed_control,
480                          NV_SWITCH_REGKEY_SPEED_CONTROL,
481                          NV_SWITCH_REGKEY_SPEED_CONTROL_SPEED_DEFAULT);
482 
483     NVSWITCH_INIT_REGKEY(_PRIVATE, inforom_bbx_periodic_flush,
484                          NV_SWITCH_REGKEY_INFOROM_BBX_ENABLE_PERIODIC_FLUSHING,
485                          NV_SWITCH_REGKEY_INFOROM_BBX_ENABLE_PERIODIC_FLUSHING_DISABLE);
486 
487     NVSWITCH_INIT_REGKEY(_PRIVATE, inforom_bbx_write_periodicity,
488                          NV_SWITCH_REGKEY_INFOROM_BBX_WRITE_PERIODICITY,
489                          NV_SWITCH_REGKEY_INFOROM_BBX_WRITE_PERIODICITY_DEFAULT);
490 
491     NVSWITCH_INIT_REGKEY(_PRIVATE, inforom_bbx_write_min_duration,
492                          NV_SWITCH_REGKEY_INFOROM_BBX_WRITE_MIN_DURATION,
493                          NV_SWITCH_REGKEY_INFOROM_BBX_WRITE_MIN_DURATION_DEFAULT);
494 
495     NVSWITCH_INIT_REGKEY(_PRIVATE, minion_disable,
496                          NV_SWITCH_REGKEY_MINION_DISABLE,
497                          NV_SWITCH_REGKEY_MINION_DISABLE_NO);
498 
499     NVSWITCH_INIT_REGKEY(_PRIVATE, set_ucode_target,
500                          NV_SWITCH_REGKEY_MINION_SET_UCODE_TARGET,
501                          NV_SWITCH_REGKEY_MINION_SET_UCODE_TARGET_DEFAULT);
502 
503     NVSWITCH_INIT_REGKEY(_PRIVATE, set_simmode,
504                          NV_SWITCH_REGKEY_MINION_SET_SIMMODE,
505                          NV_SWITCH_REGKEY_MINION_SET_SIMMODE_DEFAULT);
506 
507     NVSWITCH_INIT_REGKEY(_PRIVATE, set_smf_settings,
508                          NV_SWITCH_REGKEY_MINION_SET_SMF_SETTINGS,
509                          NV_SWITCH_REGKEY_MINION_SET_SMF_SETTINGS_DEFAULT);
510 
511     NVSWITCH_INIT_REGKEY(_PRIVATE, select_uphy_tables,
512                          NV_SWITCH_REGKEY_MINION_SELECT_UPHY_TABLES,
513                          NV_SWITCH_REGKEY_MINION_SELECT_UPHY_TABLES_DEFAULT);
514 
515     NVSWITCH_INIT_REGKEY(_PRIVATE, link_training_mode,
516                          NV_SWITCH_REGKEY_LINK_TRAINING_SELECT,
517                          NV_SWITCH_REGKEY_LINK_TRAINING_SELECT_DEFAULT);
518 
519     NVSWITCH_INIT_REGKEY(_PRIVATE, i2c_access_control,
520                          NV_SWITCH_REGKEY_I2C_ACCESS_CONTROL,
521                          NV_SWITCH_REGKEY_I2C_ACCESS_CONTROL_DEFAULT);
522 
523     NVSWITCH_INIT_REGKEY(_PRIVATE, force_kernel_i2c,
524                          NV_SWITCH_REGKEY_FORCE_KERNEL_I2C,
525                          NV_SWITCH_REGKEY_FORCE_KERNEL_I2C_DEFAULT);
526 
527     NVSWITCH_INIT_REGKEY(_PRIVATE, link_recal_settings,
528                          NV_SWITCH_REGKEY_LINK_RECAL_SETTINGS,
529                          NV_SWITCH_REGKEY_LINK_RECAL_SETTINGS_NOP);
530 
531     NVSWITCH_INIT_REGKEY(_PRIVATE, lp_threshold,
532                          NV_SWITCH_REGKEY_SET_LP_THRESHOLD,
533                          NV_SWITCH_REGKEY_SET_LP_THRESHOLD_DEFAULT);
534 
535     NVSWITCH_INIT_REGKEY(_PUBLIC, minion_intr,
536                          NV_SWITCH_REGKEY_MINION_INTERRUPTS,
537                          NV_SWITCH_REGKEY_MINION_INTERRUPTS_DEFAULT);
538 
539     NVSWITCH_INIT_REGKEY(_PRIVATE, block_code_mode,
540                          NV_SWITCH_REGKEY_BLOCK_CODE_MODE,
541                          NV_SWITCH_REGKEY_BLOCK_CODE_MODE_DEFAULT);
542 
543     NVSWITCH_INIT_REGKEY(_PRIVATE, reference_clock_mode,
544                          NV_SWITCH_REGKEY_REFERENCE_CLOCK_MODE,
545                          NV_SWITCH_REGKEY_REFERENCE_CLOCK_MODE_DEFAULT);
546 }
547 NvU64
548 nvswitch_lib_deferred_task_dispatcher
549 (
550     nvswitch_device *device
551 )
552 {
553     NvU64 time_nsec;
554     NvU64 time_next_nsec = nvswitch_os_get_platform_time() + 100*NVSWITCH_INTERVAL_1MSEC_IN_NS;
555     NVSWITCH_TASK_TYPE *task;
556     NVSWITCH_TASK_TYPE *prev_task;
557 
558     if (!NVSWITCH_IS_DEVICE_VALID(device))
559     {
560         return NV_U64_MAX;
561     }
562 
563     prev_task = NULL;
564     task = device->tasks;
565 
566     // Walk the task list, executing those whose next execution interval is at hand
567     while (task)
568     {
569         // Get current time (nsec) for scheduling
570         time_nsec = nvswitch_os_get_platform_time();
571 
572         if (time_nsec >= task->last_run_nsec + task->period_nsec)
573         {
574             //
575             // The task has never been run or it is time to run
576             // Mark its last run time
577             //
578             task->last_run_nsec = time_nsec;
579             // Run the task
580             if (NVSWITCH_IS_DEVICE_INITIALIZED(device) ||
581                (task->flags & NVSWITCH_TASK_TYPE_FLAGS_RUN_EVEN_IF_DEVICE_NOT_INITIALIZED))
582             {
583                 if(task->flags & NVSWITCH_TASK_TYPE_FLAGS_VOID_PTR_ARGS)
584                     (*task->task_fn_vdptr)(device, task->task_args);  // run task with provided args
585                 else
586                     (*task->task_fn_devptr)(device);
587             }
588         }
589 
590         // Determine its next run time
591         time_next_nsec = NV_MIN(task->last_run_nsec + task->period_nsec, time_next_nsec);
592 
593         // Advance pointer. If run once flag is set and task ran, remove task from list.
594         if((task->flags & NVSWITCH_TASK_TYPE_FLAGS_RUN_ONCE) &&
595            (task->last_run_nsec == time_nsec))
596         {
597             prev_task = task->prev;
598 
599             // Removing from list head
600             if (prev_task == NULL)
601             {
602                 device->tasks = task->next;
603                 if (device->tasks != NULL)
604                 {
605                     device->tasks->prev = NULL;
606                 }
607                 nvswitch_os_free(task);
608                 task = device->tasks;
609             }
610             else
611             {
612                 prev_task->next = task->next;
613                 if (prev_task->next != NULL)
614                 {
615                     prev_task->next->prev = prev_task;
616                 }
617                 nvswitch_os_free(task);
618                 task = prev_task->next;
619             }
620         }
621         else
622         {
623             task = task->next;
624         }
625     }
626 
627     time_nsec = nvswitch_os_get_platform_time();
628 
629     // Return to the OS layer how long to wait before calling again
630     return(time_next_nsec >= time_nsec ? time_next_nsec - time_nsec : 0);
631 }
632 
633 static NvlStatus
634 _nvswitch_setup_hal
635 (
636     nvswitch_device *device,
637     NvU32 pci_device_id
638 )
639 {
640     if (nvswitch_is_lr10_device_id(pci_device_id))
641     {
642         nvswitch_setup_hal_lr10(device);
643         return NVL_SUCCESS;
644     }
645     if (nvswitch_is_ls10_device_id(pci_device_id))
646     {
647         nvswitch_setup_hal_ls10(device);
648         return NVL_SUCCESS;
649     }
650     NVSWITCH_PRINT(device, ERROR,
651         "NVSwitch HAL setup failed - Unrecognized PCI Device ID\n");
652     return -NVL_ERR_NOT_SUPPORTED;
653 }
654 
655 NvlStatus
656 nvswitch_lib_check_api_version
657 (
658     const char *user_version,
659     char *kernel_version,
660     NvU32 length
661 )
662 {
663     const NvLength VERSION_LENGTH = nvswitch_os_strlen(NV_VERSION_STRING);
664 
665     if (kernel_version == NULL || user_version == NULL)
666     {
667         return -NVL_BAD_ARGS;
668     }
669 
670     if (length < VERSION_LENGTH)
671     {
672         return -NVL_NO_MEM;
673     }
674 
675     nvswitch_os_memset(kernel_version, 0x0, length);
676     nvswitch_os_strncpy(kernel_version, NV_VERSION_STRING, VERSION_LENGTH);
677 
678     kernel_version[length - 1] = '\0';
679 
680     if (nvswitch_os_strncmp(user_version, kernel_version, VERSION_LENGTH))
681     {
682         return -NVL_ERR_NOT_SUPPORTED;
683     }
684 
685     return NVL_SUCCESS;
686 }
687 
688 NvBool
689 nvswitch_is_inforom_supported
690 (
691     nvswitch_device *device
692 )
693 {
694     return device->hal.nvswitch_is_inforom_supported(device);
695 }
696 
697 NvBool
698 nvswitch_is_spi_supported
699 (
700     nvswitch_device *device
701 )
702 {
703     return device->hal.nvswitch_is_spi_supported(device);
704 }
705 
706 NvBool
707 nvswitch_is_bios_supported
708 (
709     nvswitch_device *device
710 )
711 {
712     return device->hal.nvswitch_is_bios_supported(device);
713 }
714 
715 NvBool
716 nvswitch_is_smbpbi_supported
717 (
718     nvswitch_device *device
719 )
720 {
721     return device->hal.nvswitch_is_smbpbi_supported(device);
722 }
723 
724 NvBool
725 nvswitch_is_soe_supported
726 (
727     nvswitch_device *device
728 )
729 {
730     if (device->regkeys.soe_disable == NV_SWITCH_REGKEY_SOE_DISABLE_YES)
731     {
732         NVSWITCH_PRINT(device, INFO, "SOE is disabled via regkey.\n");
733         return NV_FALSE;
734     }
735 
736     return device->hal.nvswitch_is_soe_supported(device);
737 }
738 
739 
740 NvlStatus
741 nvswitch_init_soe
742 (
743     nvswitch_device *device
744 )
745 {
746     if (device->regkeys.soe_disable == NV_SWITCH_REGKEY_SOE_DISABLE_YES)
747     {
748         NVSWITCH_PRINT(device, INFO, "SOE is disabled via regkey.\n");
749         return NV_FALSE;
750     }
751 
752     return device->hal.nvswitch_init_soe(device);
753 }
754 
755 void
756 nvswitch_soe_init_l2_state
757 (
758     nvswitch_device *device
759 )
760 {
761     device->hal.nvswitch_soe_init_l2_state(device);
762 }
763 
764 static NvlStatus
765 _nvswitch_construct_soe
766 (
767     nvswitch_device *device
768 )
769 {
770     FLCNABLE *pSoe = NULL;
771     NvlStatus retval;
772 
773     device->pSoe = pSoe = (PFLCNABLE)soeAllocNew();
774     if (pSoe == NULL)
775     {
776         NVSWITCH_PRINT(device, ERROR, "SOE allocation failed.\n");
777         return -NVL_NO_MEM;
778     }
779 
780     retval = soeInit(device, (PSOE)pSoe, device->nvlink_device->pciInfo.pciDeviceId);
781     if (retval != NVL_SUCCESS)
782     {
783         NVSWITCH_PRINT(device, ERROR, "SOE init failed.\n");
784         goto soe_init_failed;
785     }
786 
787     if (flcnableConstruct_HAL(device, pSoe) != NV_OK)
788     {
789         NVSWITCH_PRINT(device, ERROR, "FALCON construct failed.\n");
790         retval = -NVL_ERR_INVALID_STATE;
791         goto flcn_construct_failed;
792     }
793 
794     return NVL_SUCCESS;
795 
796 flcn_construct_failed:
797     soeDestroy(device, (PSOE)pSoe);
798 
799 soe_init_failed:
800     nvswitch_os_free(pSoe);
801     device->pSoe = NULL;
802 
803     return retval;
804 }
805 
806 static void
807 _nvswitch_destruct_soe
808 (
809     nvswitch_device *device
810 )
811 {
812     FLCNABLE *pSoe = device->pSoe;
813 
814     if (pSoe == NULL)
815     {
816         return;
817     }
818 
819     flcnableDestruct_HAL(device, pSoe);
820     soeDestroy(device, (PSOE)pSoe);
821 
822     nvswitch_os_free(pSoe);
823     device->pSoe = NULL;
824 }
825 
826 static NvlStatus
827 _nvswitch_initialize_device_state
828 (
829     nvswitch_device *device
830 )
831 {
832     return device->hal.nvswitch_initialize_device_state(device);
833 }
834 
835 static NvlStatus
836 _nvswitch_post_init_device_setup
837 (
838     nvswitch_device *device
839 )
840 {
841     return device->hal.nvswitch_post_init_device_setup(device);
842 }
843 
844 static NvlStatus
845 _nvswitch_setup_system_registers
846 (
847     nvswitch_device *device
848 )
849 {
850     return device->hal.nvswitch_setup_system_registers(device);
851 }
852 
853 static void
854 _nvswitch_post_init_blacklist_device_setup
855 (
856     nvswitch_device *device
857 )
858 {
859     device->hal.nvswitch_post_init_blacklist_device_setup(device);
860 }
861 
862 static void
863 _nvswitch_set_dma_mask
864 (
865     nvswitch_device *device
866 )
867 {
868     NvU32 hw_dma_width, retval;
869 
870     hw_dma_width = device->hal.nvswitch_get_device_dma_width(device);
871 
872     if (hw_dma_width == 0)
873     {
874         NVSWITCH_PRINT(device, INFO, "DMA is not supported on this device\n");
875         return;
876     }
877 
878     retval = nvswitch_os_set_dma_mask(device->os_handle, hw_dma_width);
879     if (retval == NVL_SUCCESS)
880     {
881         device->dma_addr_width = hw_dma_width;
882         return;
883     }
884 
885     NVSWITCH_PRINT(device, SETUP,
886                    "%s: Failed to set DMA mask, trying 32-bit fallback : %d\n",
887                    __FUNCTION__, retval);
888 
889     retval = nvswitch_os_set_dma_mask(device->os_handle, 32);
890     if (retval == NVL_SUCCESS)
891     {
892         device->dma_addr_width = 32;
893         return;
894     }
895 
896     // failure is not fatal, the driver will just restrict DMA functionality
897     NVSWITCH_PRINT(device, ERROR, "Failed to set DMA mask : %d\n", retval);
898 }
899 
900 NvlStatus
901 nvswitch_deassert_link_reset
902 (
903     nvswitch_device *device,
904     nvlink_link *link
905 )
906 {
907     return device->hal.nvswitch_deassert_link_reset(device, link);
908 }
909 
910 NvU32
911 nvswitch_get_sublink_width
912 (
913     nvswitch_device *device,
914     NvU32 linkNumber
915 )
916 {
917     return device->hal.nvswitch_get_sublink_width(device, linkNumber);
918 }
919 
920 static void
921 _nvswitch_unregister_links
922 (
923     nvswitch_device *device
924 )
925 {
926     nvlink_link *link = NULL;
927     NvU32 link_num;
928     NvBool is_blacklisted;
929 
930 
931     if (!NVSWITCH_IS_DEVICE_INITIALIZED(device))
932         return;
933 
934     device->nvlink_device->initialized = 0;
935     is_blacklisted = (device->device_fabric_state == NVSWITCH_DEVICE_FABRIC_STATE_BLACKLISTED);
936 
937     for (link_num = 0; link_num < nvswitch_get_num_links(device); link_num++)
938     {
939         if (nvlink_lib_get_link(device->nvlink_device, link_num, &link) == NVL_SUCCESS)
940         {
941             nvlink_lib_unregister_link(link);
942             nvswitch_destroy_link(link);
943         }
944     }
945 
946     if (!is_blacklisted)
947         nvswitch_inforom_nvlink_flush(device);
948 }
949 
950 NvlStatus NV_API_CALL
951 nvswitch_lib_read_fabric_state
952 (
953     nvswitch_device *device,
954     NVSWITCH_DEVICE_FABRIC_STATE *device_fabric_state,
955     NVSWITCH_DEVICE_BLACKLIST_REASON *device_blacklist_reason,
956     NVSWITCH_DRIVER_FABRIC_STATE *driver_fabric_state
957 )
958 {
959     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
960         return -NVL_BAD_ARGS;
961 
962     if (device_fabric_state != NULL)
963         *device_fabric_state = device->device_fabric_state;
964 
965     if (device_blacklist_reason != NULL)
966         *device_blacklist_reason = device->device_blacklist_reason;
967 
968     if (driver_fabric_state != NULL)
969         *driver_fabric_state = device->driver_fabric_state;
970 
971     return NVL_SUCCESS;
972 }
973 
974 static NvlStatus
975 nvswitch_lib_blacklist_device
976 (
977     nvswitch_device *device,
978     NVSWITCH_DEVICE_BLACKLIST_REASON device_blacklist_reason
979 )
980 {
981     NvlStatus status;
982 
983     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
984     {
985         return -NVL_BAD_ARGS;
986     }
987 
988     if (device->device_fabric_state == NVSWITCH_DEVICE_FABRIC_STATE_BLACKLISTED)
989     {
990         NVSWITCH_PRINT(device, WARN, "Device is already blacklisted\n");
991         return -NVL_ERR_NOT_SUPPORTED;
992     }
993 
994     device->device_fabric_state = NVSWITCH_DEVICE_FABRIC_STATE_BLACKLISTED;
995     device->device_blacklist_reason = device_blacklist_reason;
996 
997     status = device->hal.nvswitch_write_fabric_state(device);
998     if (status != NVL_SUCCESS)
999         NVSWITCH_PRINT(device, INFO, "Cannot send fabric state to SOE\n");
1000 
1001     return NVL_SUCCESS;
1002 }
1003 
1004 static NvlStatus
1005 nvswitch_ctrl_blacklist_device(
1006     nvswitch_device *device,
1007     NVSWITCH_BLACKLIST_DEVICE_PARAMS *p
1008 )
1009 {
1010     NvlStatus status;
1011 
1012     status = nvswitch_lib_blacklist_device(device, p->deviceReason);
1013     if (status != NVL_SUCCESS)
1014         return status;
1015 
1016     nvswitch_lib_disable_interrupts(device);
1017 
1018     // Unregister links from NVLinkCoreLib, so that link training is not
1019     // attempted
1020     _nvswitch_unregister_links(device);
1021 
1022     // Keep device registered for HAL access and Fabric State updates
1023 
1024     return NVL_SUCCESS;
1025 }
1026 
1027 static NvlStatus
1028 nvswitch_ctrl_set_fm_driver_state(
1029     nvswitch_device *device,
1030     NVSWITCH_SET_FM_DRIVER_STATE_PARAMS *p
1031 )
1032 {
1033     NvU32 prev_fm_status;
1034 
1035     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1036     {
1037         return -NVL_BAD_ARGS;
1038     }
1039 
1040     prev_fm_status = device->driver_fabric_state;
1041     device->driver_fabric_state = p->driverState;
1042     device->fabric_state_timestamp = nvswitch_os_get_platform_time();
1043 
1044     if (prev_fm_status != p->driverState)
1045     {
1046         if (nvswitch_lib_notify_client_events(device,
1047             NVSWITCH_DEVICE_EVENT_FABRIC_STATE) != NVL_SUCCESS)
1048         {
1049             NVSWITCH_PRINT(device, ERROR, "%s: Failed to notify event\n",
1050                            __FUNCTION__);
1051         }
1052     }
1053 
1054     return NVL_SUCCESS;
1055 }
1056 
1057 static NvlStatus
1058 nvswitch_ctrl_set_device_fabric_state(
1059     nvswitch_device *device,
1060     NVSWITCH_SET_DEVICE_FABRIC_STATE_PARAMS *p
1061 )
1062 {
1063     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1064     {
1065         return -NVL_BAD_ARGS;
1066     }
1067 
1068     if (device->device_fabric_state == NVSWITCH_DEVICE_FABRIC_STATE_BLACKLISTED)
1069         return -NVL_ERR_NOT_SUPPORTED;
1070 
1071     device->device_fabric_state = p->deviceState;
1072     device->fabric_state_timestamp = nvswitch_os_get_platform_time();
1073 
1074     // If FM had exceeded timeout, reset the status to not timed-out
1075     if (device->driver_fabric_state == NVSWITCH_DRIVER_FABRIC_STATE_MANAGER_TIMEOUT)
1076         device->driver_fabric_state = NVSWITCH_DRIVER_FABRIC_STATE_CONFIGURED;
1077 
1078     return NVL_SUCCESS;
1079 }
1080 
1081 static NvlStatus
1082 nvswitch_ctrl_set_fm_timeout(
1083     nvswitch_device *device,
1084     NVSWITCH_SET_FM_HEARTBEAT_TIMEOUT_PARAMS *p
1085 )
1086 {
1087     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1088     {
1089         return -NVL_BAD_ARGS;
1090     }
1091 
1092     device->fm_timeout = p->fmTimeout;
1093 
1094     return NVL_SUCCESS;
1095 }
1096 
1097 static NvlStatus
1098 _nvswitch_ctrl_register_events(
1099     nvswitch_device *device,
1100     NVSWITCH_REGISTER_EVENTS_PARAMS *p,
1101     void *osPrivate
1102 )
1103 {
1104     NvlStatus status = NVL_SUCCESS;
1105     NvU32 i;
1106     NvBool many_events, os_descriptor;
1107     void *osDescriptor = osPrivate;
1108 
1109     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1110     {
1111         return -NVL_BAD_ARGS;
1112     }
1113 
1114     status = nvswitch_os_get_supported_register_events_params(&many_events,
1115                                                               &os_descriptor);
1116     if (status != NVL_SUCCESS)
1117     {
1118         return status;
1119     }
1120 
1121     if ((!many_events && (p->numEvents > 1)) ||
1122         (p->numEvents == 0))
1123     {
1124         return -NVL_BAD_ARGS;
1125     }
1126 
1127     if (os_descriptor)
1128     {
1129         osDescriptor = (void *) p->osDescriptor;
1130     }
1131 
1132     for (i = 0; i < p->numEvents; i++)
1133     {
1134         status = nvswitch_lib_add_client_event(device, osDescriptor, p->eventIds[i]);
1135         if (status != NVL_SUCCESS)
1136         {
1137             NVSWITCH_PRINT(device, ERROR, "%s: Failed to add client event.\n", __FUNCTION__);
1138             return status;
1139         }
1140     }
1141 
1142     return NVL_SUCCESS;
1143 }
1144 
1145 static NvlStatus
1146 _nvswitch_ctrl_unregister_events(
1147     nvswitch_device *device,
1148     NVSWITCH_UNREGISTER_EVENTS_PARAMS *p,
1149     void *osPrivate
1150 )
1151 {
1152     NvlStatus status = NVL_SUCCESS;
1153     NvBool many_events, os_descriptor;
1154     void *osDescriptor = osPrivate;
1155 
1156     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1157     {
1158         return -NVL_BAD_ARGS;
1159     }
1160 
1161     status = nvswitch_os_get_supported_register_events_params(&many_events,
1162                                                               &os_descriptor);
1163     if (status != NVL_SUCCESS)
1164     {
1165         return status;
1166     }
1167 
1168     if (os_descriptor)
1169     {
1170         osDescriptor = (void *) p->osDescriptor;
1171     }
1172 
1173     status = nvswitch_lib_remove_client_events(device, osDescriptor);
1174     if (status != NVL_SUCCESS)
1175     {
1176         NVSWITCH_PRINT(device, ERROR, "%s: Failed to remove client event.\n", __FUNCTION__);
1177         return status;
1178     }
1179 
1180     return NVL_SUCCESS;
1181 }
1182 
1183 /*
1184  * @Brief : Sends NACK or drops given inband msg based on message type
1185  *
1186  * @Description :
1187  *
1188  * @param[in] device            NvSwitch device to contain this link
1189  * @param[in] linkId            Link ID
1190  * @param[in] msghdr            Header to the message
1191  *
1192  */
1193 static void
1194 nvswitch_send_nack_or_drop
1195 (
1196     nvswitch_device            *device,
1197     NvU32                       linkId,
1198     nvlink_inband_msg_header_t *msghdr
1199 )
1200 {
1201     switch(msghdr->type)
1202     {
1203         case NVLINK_INBAND_MSG_TYPE_MC_TEAM_SETUP_REQ:
1204             device->hal.nvswitch_send_inband_nack(device, (NvU32 *)msghdr, linkId);
1205             NVSWITCH_PRINT(device, ERROR,
1206                            "Sending NACK for message (type 0x%x)\n", msghdr->type);
1207             return;
1208         default:
1209             // TODO: Add SXid in future if needed.
1210             NVSWITCH_PRINT(device, ERROR,
1211                            "Dropping message (type 0x%x)\n", msghdr->type);
1212             return;
1213     }
1214 }
1215 
1216 /*
1217  * @Brief : Deletes all the entries in persistent or non-persistent lists.
1218  *          Send nacks if requested.
1219  *
1220  * @Description :
1221  *
1222  * @param[in] device              NVSwitch device to contain this link
1223  * @param[in] linkId              Link number
1224  * @param[in] bSendNack           Send nacks if true
1225  * @param[in] bNonPersistentOnly  Clear only non-persistent list
1226  */
1227 static void
1228 _nvswitch_inband_clear_lists
1229 (
1230     nvswitch_device *device,
1231     NvU32            linkId,
1232     NvBool           bSendNack,
1233     NvBool           bNonPersistentOnly
1234 )
1235 {
1236     nvswitch_inband_data_list *curr = NULL;
1237     nvswitch_inband_data_list *next = NULL;
1238     nvlink_inband_msg_header_t *msghdr = NULL;
1239 
1240     nvListForEachEntry_safe(curr, next,
1241                     &device->link[linkId].inbandData.nonpersistent_list, entry)
1242     {
1243         if (bSendNack)
1244         {
1245             msghdr = (nvlink_inband_msg_header_t *)curr->data;
1246             nvswitch_send_nack_or_drop(device, linkId, msghdr);
1247         }
1248 
1249         nvListDel(&curr->entry);
1250         nvswitch_os_free(curr);
1251     }
1252 
1253     if (bNonPersistentOnly)
1254         return;
1255 
1256     nvListForEachEntry_safe(curr, next,
1257                     &device->link[linkId].inbandData.persistent_list, entry)
1258     {
1259         if (bSendNack)
1260         {
1261             msghdr = (nvlink_inband_msg_header_t *)curr->data;
1262             nvswitch_send_nack_or_drop(device, linkId, msghdr);
1263         }
1264 
1265         nvListDel(&curr->entry);
1266         nvswitch_os_free(curr);
1267     }
1268 }
1269 
1270 static void
1271 nvswitch_fabric_state_heartbeat(
1272     nvswitch_device *device
1273 )
1274 {
1275     NvU64 age;
1276     NvU32 linkId;
1277 
1278     if (!NVSWITCH_IS_DEVICE_VALID(device))
1279         return;
1280 
1281     age = nvswitch_os_get_platform_time() - device->fabric_state_timestamp;
1282 
1283     // Check to see if we have exceeded the FM timeout
1284     if (device->driver_fabric_state == NVSWITCH_DRIVER_FABRIC_STATE_CONFIGURED &&
1285         age > (NvU64)device->fm_timeout * 1000ULL * 1000ULL)
1286          device->driver_fabric_state = NVSWITCH_DRIVER_FABRIC_STATE_MANAGER_TIMEOUT;
1287 
1288     //
1289     // If FM is not running, clear pending non-persistent messages. Persistent
1290     // messages can be processed by the FM when it restarts.
1291     //
1292     if (device->driver_fabric_state != NVSWITCH_DRIVER_FABRIC_STATE_CONFIGURED)
1293     {
1294         for (linkId = 0; linkId < nvswitch_get_num_links(device); linkId++)
1295             _nvswitch_inband_clear_lists(device, linkId,
1296                                          NV_TRUE /* Nack */,
1297                                          NV_TRUE /* Non-persistent only */);
1298     }
1299 
1300     (void)device->hal.nvswitch_write_fabric_state(device);
1301 }
1302 
1303 static NvlStatus
1304 _nvswitch_ctrl_set_training_error_info
1305 (
1306     nvswitch_device *device,
1307     NVSWITCH_SET_TRAINING_ERROR_INFO_PARAMS *p
1308 )
1309 {
1310     return device->hal.nvswitch_set_training_error_info(device, p);
1311 }
1312 
1313 static NvlStatus
1314 _nvswitch_ctrl_get_fatal_error_scope
1315 (
1316     nvswitch_device *device,
1317     NVSWITCH_GET_FATAL_ERROR_SCOPE_PARAMS *pParams
1318 )
1319 {
1320     return device->hal.nvswitch_ctrl_get_fatal_error_scope(device, pParams);
1321 }
1322 
1323 static NvlStatus
1324 _nvswitch_ctrl_therm_get_temperature_limit
1325 (
1326     nvswitch_device *device,
1327     NVSWITCH_CTRL_GET_TEMPERATURE_LIMIT_PARAMS *pParams
1328 )
1329 {
1330     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1331     {
1332         return -NVL_BAD_ARGS;
1333     }
1334 
1335     return device->hal.nvswitch_ctrl_therm_get_temperature_limit(device, pParams);
1336 }
1337 
1338 NvlStatus
1339 nvswitch_lib_initialize_device
1340 (
1341     nvswitch_device *device
1342 )
1343 {
1344     NvlStatus retval = NVL_SUCCESS;
1345     NvU8 link_num;
1346     nvlink_link *link = NULL;
1347     NvBool is_blacklisted_by_os = NV_FALSE;
1348     NvU64 mode;
1349 
1350     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1351     {
1352         return -NVL_BAD_ARGS;
1353     }
1354 
1355     if (NVSWITCH_IS_DEVICE_INITIALIZED(device))
1356     {
1357         NVSWITCH_PRINT(device, SETUP, "Device is already initialized!\n");
1358         return NVL_SUCCESS;
1359     }
1360 
1361     NVSWITCH_PRINT(device, SETUP,
1362         "Initializing nvswitch at (%04x:%02x:%02x.%02x)\n",
1363         device->nvlink_device->pciInfo.domain,
1364         device->nvlink_device->pciInfo.bus,
1365         device->nvlink_device->pciInfo.device,
1366         device->nvlink_device->pciInfo.function);
1367 
1368     nvListInit(&device->client_events_list);
1369 
1370     for (link_num=0; link_num < nvswitch_get_num_links(device); link_num++)
1371     {
1372         nvListInit(&device->link[link_num].inbandData.persistent_list);
1373         nvListInit(&device->link[link_num].inbandData.nonpersistent_list);
1374     }
1375 
1376     retval = nvswitch_lib_load_platform_info(device);
1377     if (retval != NVL_SUCCESS)
1378     {
1379         NVSWITCH_PRINT(device, ERROR, "Failed to load platform information\n");
1380         return retval;
1381     }
1382 
1383     if (nvswitch_is_soe_supported(device))
1384     {
1385         retval = _nvswitch_construct_soe(device);
1386         if (retval != NVL_SUCCESS)
1387         {
1388             return retval;
1389         }
1390     }
1391     else
1392     {
1393         NVSWITCH_PRINT(device, INFO, "SOE is not supported, skipping construct\n");
1394     }
1395 
1396     _nvswitch_set_dma_mask(device);
1397 
1398     retval = _nvswitch_initialize_device_state(device);
1399     if (NVL_SUCCESS != retval)
1400     {
1401         NVSWITCH_PRINT(device, ERROR,
1402             "Failed to initialize device state: %d!\n",
1403             retval);
1404         goto nvswitch_initialize_device_state_fail;
1405     }
1406 
1407     device->hal.nvswitch_load_uuid(device);
1408 
1409     /*
1410      * Check module parameters for blacklisted device
1411      */
1412     if (nvswitch_os_is_uuid_in_blacklist(&device->uuid) == NV_TRUE)
1413     {
1414         NVSWITCH_PRINT(device, SETUP,
1415             "Blacklisted nvswitch at (%04x:%02x:%02x.%02x)\n",
1416             device->nvlink_device->pciInfo.domain,
1417             device->nvlink_device->pciInfo.bus,
1418             device->nvlink_device->pciInfo.device,
1419             device->nvlink_device->pciInfo.function);
1420         is_blacklisted_by_os = NV_TRUE;
1421         // initialization continues until we have updated InfoROM...
1422     }
1423 
1424     if (nvswitch_is_inforom_supported(device))
1425     {
1426         retval = nvswitch_initialize_inforom(device);
1427         if (NVL_SUCCESS != retval)
1428         {
1429             NVSWITCH_PRINT(device, ERROR,
1430                     "Failed to initialize InfoROM rc: %d\n",
1431                     retval);
1432             goto nvswitch_initialize_device_state_fail;
1433         }
1434 
1435         retval = nvswitch_initialize_inforom_objects(device);
1436         if (NVL_SUCCESS != retval)
1437         {
1438             NVSWITCH_PRINT(device, ERROR,
1439                         "Failed to initialize InfoROM objects! rc:%d\n",
1440                         retval);
1441             goto nvswitch_initialize_inforom_fail;
1442         }
1443     }
1444     else
1445     {
1446         NVSWITCH_PRINT(device, INFO,
1447                 "InfoROM is not supported, skipping init\n");
1448     }
1449 
1450     (void)device->hal.nvswitch_read_oob_blacklist_state(device);
1451     (void)device->hal.nvswitch_write_fabric_state(device);
1452 
1453     nvswitch_task_create(device, &nvswitch_fabric_state_heartbeat,
1454                          NVSWITCH_HEARTBEAT_INTERVAL_NS,
1455                          NVSWITCH_TASK_TYPE_FLAGS_RUN_EVEN_IF_DEVICE_NOT_INITIALIZED);
1456 
1457     //
1458     // Blacklisted devices return successfully in order to preserve the fabric state heartbeat
1459     // and ensure OOB utilities don't think the driver has died
1460     //
1461     if (device->device_blacklist_reason == NVSWITCH_DEVICE_BLACKLIST_REASON_MANUAL_OUT_OF_BAND)
1462     {
1463         NVSWITCH_PRINT(device, SETUP,
1464             "Blacklisted nvswitch at (%04x:%02x:%02x.%02x)\n",
1465             device->nvlink_device->pciInfo.domain,
1466             device->nvlink_device->pciInfo.bus,
1467             device->nvlink_device->pciInfo.device,
1468             device->nvlink_device->pciInfo.function);
1469         return NVL_SUCCESS;
1470     }
1471 
1472     if (is_blacklisted_by_os)
1473     {
1474         (void)nvswitch_lib_blacklist_device(device, NVSWITCH_DEVICE_BLACKLIST_REASON_MANUAL_IN_BAND);
1475         return NVL_SUCCESS;
1476     }
1477 
1478     for (link_num=0; link_num < nvswitch_get_num_links(device); link_num++)
1479     {
1480         if (!nvswitch_is_link_valid(device, link_num))
1481         {
1482             continue;
1483         }
1484 
1485         retval = nvswitch_create_link(device, link_num, &link);
1486         if (NVL_SUCCESS != retval)
1487         {
1488             NVSWITCH_PRINT(device, ERROR,
1489                 "Failed to create link %d : %d!\n",
1490                 link_num,
1491                 retval);
1492             goto nvswitch_link_fail;
1493         }
1494 
1495         retval = nvlink_lib_register_link(device->nvlink_device, link);
1496         if (NVL_SUCCESS != retval)
1497         {
1498             NVSWITCH_PRINT(device, ERROR,
1499                 "Failed to register link %d with the nvlink core : %d!\n",
1500                 link_num,
1501                 retval);
1502 
1503             // Free the single dangling link.
1504             nvswitch_destroy_link(link);
1505 
1506             goto nvswitch_link_fail;
1507         }
1508 
1509         nvswitch_reset_persistent_link_hw_state(device, link_num);
1510 
1511         if(_nvswitch_corelib_get_dl_link_mode(link, &mode) != NVL_SUCCESS)
1512         {
1513             NVSWITCH_PRINT(device, ERROR, "%s: nvlipt_lnk_status: Failed to check link mode! LinkId %d\n",
1514                         __FUNCTION__, link_num);
1515         }
1516         else if(mode == NVLINK_LINKSTATE_FAULT)
1517         {
1518             NVSWITCH_PRINT(device, INFO, "%s: retraining LinkId %d\n",
1519                         __FUNCTION__, link_num);
1520             nvswitch_reset_and_train_link(device, link);
1521         }
1522 
1523     }
1524 
1525     retval = nvswitch_set_training_mode(device);
1526 
1527     if (retval != NVL_SUCCESS)
1528     {
1529         NVSWITCH_PRINT(device, ERROR, "Failed to determine link training mode! rc: %d\n", retval);
1530         goto nvswitch_link_fail;
1531     }
1532     // Initialize select scratch registers to 0x0
1533     device->hal.nvswitch_init_scratch(device);
1534 
1535     retval = nvswitch_construct_error_log(&device->log_FATAL_ERRORS, 1024, NV_FALSE);
1536     if (retval != NVL_SUCCESS)
1537     {
1538         NVSWITCH_PRINT(device, ERROR, "Failed to construct log_FATAL_ERRORS! rc: %d\n", retval);
1539         goto nvswitch_construct_error_log_fail;
1540     }
1541 
1542     retval = nvswitch_construct_error_log(&device->log_NONFATAL_ERRORS, 1024, NV_TRUE);
1543     if (retval != NVL_SUCCESS)
1544     {
1545         NVSWITCH_PRINT(device, ERROR, "Failed to construct log_NONFATAL_ERRORS! rc: %d\n", retval);
1546         goto nvswitch_construct_error_log_fail;
1547     }
1548 
1549     if (device->regkeys.latency_counter == NV_SWITCH_REGKEY_LATENCY_COUNTER_LOGGING_ENABLE)
1550     {
1551         nvswitch_task_create(device, &nvswitch_internal_latency_bin_log,
1552             nvswitch_get_latency_sample_interval_msec(device) * NVSWITCH_INTERVAL_1MSEC_IN_NS * 9/10, 0);
1553     }
1554 
1555     nvswitch_task_create(device, &nvswitch_ecc_writeback_task,
1556         (60 * NVSWITCH_INTERVAL_1SEC_IN_NS), 0);
1557 
1558     if (IS_RTLSIM(device) || IS_EMULATION(device) || IS_FMODEL(device))
1559     {
1560         NVSWITCH_PRINT(device, WARN,
1561         "%s: Skipping setup of NvSwitch thermal alert monitoring\n",
1562             __FUNCTION__);
1563     }
1564     else
1565     {
1566         nvswitch_task_create(device, &nvswitch_monitor_thermal_alert,
1567             100*NVSWITCH_INTERVAL_1MSEC_IN_NS, 0);
1568     }
1569 
1570     device->nvlink_device->initialized = 1;
1571 
1572     return NVL_SUCCESS;
1573 
1574 nvswitch_construct_error_log_fail:
1575     //free allocated memory to avoid leaking
1576     nvswitch_destroy_error_log(device, &device->log_FATAL_ERRORS);
1577     nvswitch_destroy_error_log(device, &device->log_NONFATAL_ERRORS);
1578 
1579 nvswitch_link_fail:
1580     // Track down all links that successfully registered.
1581     for (link_num = 0; link_num < nvswitch_get_num_links(device); link_num++)
1582     {
1583         if (nvlink_lib_get_link(device->nvlink_device, link_num, &link) == NVL_SUCCESS)
1584         {
1585             nvlink_lib_unregister_link(link);
1586             nvswitch_destroy_link(link);
1587         }
1588     }
1589 
1590     nvswitch_destroy_inforom_objects(device);
1591 
1592 nvswitch_initialize_inforom_fail:
1593     nvswitch_destroy_inforom(device);
1594 
1595 nvswitch_initialize_device_state_fail:
1596     _nvswitch_destruct_soe(device);
1597     nvswitch_tasks_destroy(device);
1598 
1599     return retval;
1600 }
1601 
1602 NvBool
1603 nvswitch_lib_validate_device_id
1604 (
1605     NvU32 device_id
1606 )
1607 {
1608     if (nvswitch_is_lr10_device_id(device_id))
1609     {
1610         return NV_TRUE;
1611     }
1612     if (nvswitch_is_ls10_device_id(device_id))
1613     {
1614         return NV_TRUE;
1615     }
1616     return NV_FALSE;
1617 }
1618 
1619 NvlStatus
1620 nvswitch_lib_post_init_device
1621 (
1622     nvswitch_device *device
1623 )
1624 {
1625     NvlStatus retval;
1626 
1627     if (!NVSWITCH_IS_DEVICE_INITIALIZED(device))
1628     {
1629         return -NVL_ERR_INVALID_STATE;
1630     }
1631 
1632     retval = _nvswitch_post_init_device_setup(device);
1633     if (retval != NVL_SUCCESS)
1634     {
1635         return retval;
1636     }
1637 
1638     if (nvswitch_is_bios_supported(device))
1639     {
1640         retval = nvswitch_bios_get_image(device);
1641         if (retval != NVL_SUCCESS)
1642         {
1643             return retval;
1644         }
1645 
1646         retval = nvswitch_parse_bios_image(device);
1647         if (retval != NVL_SUCCESS)
1648         {
1649             return retval;
1650         }
1651     }
1652     else
1653     {
1654         NVSWITCH_PRINT(device, ERROR,
1655             "%s: Skipping BIOS parsing since BIOS is unsupported.\n",
1656             __FUNCTION__);
1657     }
1658 
1659     retval = _nvswitch_setup_system_registers(device);
1660     if (retval != NVL_SUCCESS)
1661     {
1662         return retval;
1663     }
1664 
1665     nvswitch_smbpbi_post_init(device);
1666 
1667     (void)nvswitch_launch_ALI(device);
1668 
1669     return NVL_SUCCESS;
1670 }
1671 
1672 void
1673 nvswitch_lib_post_init_blacklist_device
1674 (
1675     nvswitch_device *device
1676 )
1677 {
1678     _nvswitch_post_init_blacklist_device_setup(device);
1679 }
1680 
1681 void
1682 _nvswitch_check_pending_data_and_notify
1683 (
1684     nvswitch_device       *device,
1685     NVSWITCH_CLIENT_EVENT *event
1686 )
1687 {
1688     switch (event->eventId)
1689     {
1690         case NVSWITCH_DEVICE_EVENT_INBAND_DATA:
1691         {
1692             NvU32 i;
1693 
1694             for (i = 0; i < nvswitch_get_num_links(device); i++)
1695             {
1696                 if (!nvListIsEmpty(&device->link[i].inbandData.persistent_list) ||
1697                     !nvListIsEmpty(&device->link[i].inbandData.nonpersistent_list))
1698                 {
1699                     (void)nvswitch_os_notify_client_event(device->os_handle,
1700                                                           event->private_driver_data,
1701                                                           event->eventId);
1702                 }
1703             }
1704             break;
1705         }
1706 
1707         default:
1708             return;
1709     }
1710 }
1711 
1712 /*!
1713  * @brief: Gets the client event associated with the file descriptor
1714  *         if it already exists in the Device's client event list.
1715  *
1716  *         If found, and if there is pending data for the event,
1717  *         the event is triggered before returning to unblock the
1718  *         client right away.
1719  */
1720 NvlStatus
1721 nvswitch_lib_get_client_event
1722 (
1723     nvswitch_device       *device,
1724     void                  *osPrivate,
1725     NVSWITCH_CLIENT_EVENT **ppClientEvent
1726 )
1727 {
1728     NVSWITCH_CLIENT_EVENT *curr = NULL;
1729 
1730     *ppClientEvent = NULL;
1731 
1732     if(!NVSWITCH_IS_DEVICE_VALID(device))
1733     {
1734         return -NVL_BAD_ARGS;
1735     }
1736 
1737     nvListForEachEntry(curr, &device->client_events_list, entry)
1738     {
1739         if (curr->private_driver_data == osPrivate)
1740         {
1741             *ppClientEvent = curr;
1742             _nvswitch_check_pending_data_and_notify(device, curr);
1743             return NVL_SUCCESS;
1744         }
1745     }
1746 
1747     return -NVL_NOT_FOUND;
1748 }
1749 
1750 /*!
1751  * @brief: Adds an event to the front of the
1752  *         Device's client event list.
1753  */
1754 NvlStatus
1755 nvswitch_lib_add_client_event
1756 (
1757     nvswitch_device *device,
1758     void            *osPrivate,
1759     NvU32           eventId
1760 )
1761 {
1762     NVSWITCH_CLIENT_EVENT *newEvent;
1763     NvlStatus status = NVL_SUCCESS;
1764 
1765     if (!NVSWITCH_IS_DEVICE_VALID(device))
1766     {
1767         return -NVL_BAD_ARGS;
1768     }
1769 
1770     if (eventId >= NVSWITCH_DEVICE_EVENT_COUNT)
1771     {
1772         NVSWITCH_PRINT(device, ERROR, "%s: Invalid event Id.\n", __FUNCTION__);
1773         return -NVL_BAD_ARGS;
1774     }
1775 
1776     // Invoke OS specific API to add event.
1777     status = nvswitch_os_add_client_event(device->os_handle,
1778                                           osPrivate,
1779                                           eventId);
1780     if (status != NVL_SUCCESS)
1781     {
1782         NVSWITCH_PRINT(device, ERROR, "%s: Failed to add client event.\n", __FUNCTION__);
1783         return status;
1784     }
1785 
1786     newEvent = nvswitch_os_malloc(sizeof(*newEvent));
1787     if (newEvent == NULL)
1788     {
1789         return -NVL_NO_MEM;
1790     }
1791 
1792     newEvent->eventId             = eventId;
1793     newEvent->private_driver_data = osPrivate;
1794 
1795     nvListAdd(&newEvent->entry, &device->client_events_list);
1796 
1797     return NVL_SUCCESS;
1798 }
1799 
1800 /*!
1801  * @brief: Removes all events corresponding to osPrivate,
1802  *         from the Device's client event list.
1803  */
1804 NvlStatus
1805 nvswitch_lib_remove_client_events
1806 (
1807     nvswitch_device *device,
1808     void            *osPrivate
1809 )
1810 {
1811     NVSWITCH_CLIENT_EVENT *curr = NULL;
1812     NVSWITCH_CLIENT_EVENT *next = NULL;
1813     NvlStatus status = NVL_SUCCESS;
1814 
1815     //
1816     // Device shutdown may happen before this is called, so return
1817     // if device is gone
1818     //
1819     if (!NVSWITCH_IS_DEVICE_VALID(device))
1820     {
1821         return NVL_SUCCESS;
1822     }
1823 
1824     nvListForEachEntry_safe(curr, next, &device->client_events_list, entry)
1825     {
1826         if (curr->private_driver_data == osPrivate)
1827         {
1828             nvListDel(&curr->entry);
1829             nvswitch_os_free(curr);
1830         }
1831     }
1832 
1833     // Invoke OS specific API to remove event.
1834     status = nvswitch_os_remove_client_event(device->os_handle,
1835                                              osPrivate);
1836     if (status != NVL_SUCCESS)
1837     {
1838         NVSWITCH_PRINT(device, ERROR, "%s: Failed to remove client events.\n", __FUNCTION__);
1839         return status;
1840     }
1841 
1842     return NVL_SUCCESS;
1843 }
1844 
1845 /*!
1846  * @brief: Notifies all events with matching event id in the
1847  *         Device's client event list.
1848  */
1849 NvlStatus
1850 nvswitch_lib_notify_client_events
1851 (
1852     nvswitch_device *device,
1853     NvU32            eventId
1854 )
1855 {
1856     NvlStatus status;
1857     NVSWITCH_CLIENT_EVENT *curr = NULL;
1858 
1859     if (!NVSWITCH_IS_DEVICE_VALID(device))
1860     {
1861         return -NVL_BAD_ARGS;
1862     }
1863 
1864     if (eventId >= NVSWITCH_DEVICE_EVENT_COUNT)
1865     {
1866         NVSWITCH_PRINT(device, ERROR, "%s: Invalid event Id.\n", __FUNCTION__);
1867         return -NVL_BAD_ARGS;
1868     }
1869 
1870     nvListForEachEntry(curr, &device->client_events_list, entry)
1871     {
1872         if (curr->eventId == eventId)
1873         {
1874             // OS specific event notification.
1875             status = nvswitch_os_notify_client_event(device->os_handle,
1876                                                      curr->private_driver_data,
1877                                                      eventId);
1878             if (status != NVL_SUCCESS)
1879             {
1880                 return status;
1881             }
1882         }
1883     }
1884 
1885     return NVL_SUCCESS;
1886 }
1887 
1888 /*!
1889    @brief: Release ROM image from memory.
1890 */
1891 void
1892 _nvswitch_destroy_rom(nvswitch_device *device)
1893 {
1894     if (device->biosImage.pImage != NULL)
1895     {
1896         nvswitch_os_free(device->biosImage.pImage);
1897         device->biosImage.pImage = NULL;
1898     }
1899 }
1900 
1901 /*!
1902  * @brief: Free the device's client event list
1903  */
1904 static void
1905 _nvswitch_destroy_event_list(nvswitch_device *device)
1906 {
1907     NVSWITCH_CLIENT_EVENT *curr = NULL;
1908     NVSWITCH_CLIENT_EVENT *next = NULL;
1909 
1910     nvListForEachEntry_safe(curr, next, &device->client_events_list, entry)
1911     {
1912         nvListDel(&curr->entry);
1913         nvswitch_os_free(curr);
1914     }
1915 }
1916 
1917 NvlStatus
1918 nvswitch_lib_shutdown_device
1919 (
1920     nvswitch_device *device
1921 )
1922 {
1923     NVSWITCH_INBAND_FLUSH_DATA_PARAMS p;
1924 
1925     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1926     {
1927         return -NVL_BAD_ARGS;
1928     }
1929 
1930     //
1931     // Set fabric state to offline
1932     //
1933     if (device->device_fabric_state != NVSWITCH_DEVICE_FABRIC_STATE_BLACKLISTED)
1934         device->device_fabric_state = NVSWITCH_DEVICE_FABRIC_STATE_OFFLINE;
1935     device->driver_fabric_state = NVSWITCH_DRIVER_FABRIC_STATE_OFFLINE;
1936     (void)device->hal.nvswitch_write_fabric_state(device);
1937 
1938     nvswitch_hw_counter_shutdown(device);
1939 
1940     // FLUSH any pending messages to avoid memory leaks
1941     p.linkMask = nvswitch_get_enabled_link_mask(device);
1942     _nvswitch_ctrl_inband_flush_data(device, &p);
1943 
1944     _nvswitch_unregister_links(device);
1945 
1946     nvswitch_destroy_error_log(device, &device->log_FATAL_ERRORS);
1947     nvswitch_destroy_error_log(device, &device->log_NONFATAL_ERRORS);
1948 
1949     nvswitch_smbpbi_unload(device);
1950     _nvswitch_destroy_event_list(device);
1951 
1952     nvswitch_destroy_inforom_objects(device);
1953     nvswitch_destroy_inforom(device);
1954 
1955     nvswitch_smbpbi_destroy(device);
1956 
1957     nvswitch_destroy_device_state(device);
1958 
1959     _nvswitch_destroy_rom(device);
1960 
1961     _nvswitch_destruct_soe(device);
1962 
1963     nvswitch_tasks_destroy(device);
1964 
1965     return NVL_SUCCESS;
1966 }
1967 
1968 NvlStatus
1969 nvswitch_lib_get_log_count
1970 (
1971     nvswitch_device *device,
1972     NvU32 *fatal, NvU32 *nonfatal
1973 )
1974 {
1975     if (!NVSWITCH_IS_DEVICE_INITIALIZED(device) ||
1976         fatal == NULL || nonfatal == NULL)
1977     {
1978         return -NVL_BAD_ARGS;
1979     }
1980 
1981     *fatal = device->log_FATAL_ERRORS.error_count;
1982     *nonfatal = device->log_NONFATAL_ERRORS.error_count;
1983     // No report of log_INFO currently
1984 
1985     return NVL_SUCCESS;
1986 }
1987 
1988 NvlStatus
1989 nvswitch_lib_load_platform_info
1990 (
1991     nvswitch_device *device
1992 )
1993 {
1994     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
1995     {
1996         return -NVL_BAD_ARGS;
1997     }
1998 
1999     device->hal.nvswitch_determine_platform(device);
2000 
2001     return NVL_SUCCESS;
2002 }
2003 
2004 void
2005 nvswitch_lib_get_device_info
2006 (
2007     nvswitch_device *device,
2008     struct nvlink_pci_info **pciInfo
2009 )
2010 {
2011     if (!NVSWITCH_IS_DEVICE_VALID(device) || pciInfo == NULL)
2012     {
2013         NVSWITCH_ASSERT(0);
2014         return;
2015     }
2016 
2017     *pciInfo = &device->nvlink_device->pciInfo;
2018 }
2019 
2020 NvlStatus
2021 nvswitch_lib_get_bios_version
2022 (
2023     nvswitch_device *device,
2024     NvU64 *version
2025 )
2026 {
2027     NVSWITCH_GET_BIOS_INFO_PARAMS p = { 0 };
2028     NvlStatus ret;
2029 
2030     if (!device)
2031         return -NVL_BAD_ARGS;
2032 
2033     ret = device->hal.nvswitch_ctrl_get_bios_info(device, &p);
2034 
2035     if (version != NULL)
2036     {
2037     *version = p.version;
2038     }
2039 
2040     return ret;
2041 }
2042 
2043 NvlStatus
2044 nvswitch_lib_use_pin_irq
2045 (
2046      nvswitch_device *device
2047 )
2048 {
2049     return IS_FMODEL(device);
2050 }
2051 
2052 
2053 NvlStatus
2054 nvswitch_lib_register_device
2055 (
2056     NvU16 pci_domain,
2057     NvU8 pci_bus,
2058     NvU8 pci_device,
2059     NvU8 pci_func,
2060     NvU16 pci_device_id,
2061     void *os_handle,
2062     NvU32 os_instance,
2063     nvswitch_device **return_device
2064 )
2065 {
2066     nvswitch_device *device  = NULL;
2067     nvlink_device   *coreDev = NULL;
2068     NvlStatus        retval  = NVL_SUCCESS;
2069 
2070     if (!nvlink_lib_is_initialized())
2071     {
2072         NVSWITCH_PRINT(device, ERROR,
2073             "NVLink core lib isn't initialized yet!\n");
2074         return -NVL_INITIALIZATION_TOTAL_FAILURE;
2075     }
2076 
2077     if (return_device == NULL || os_handle == NULL)
2078     {
2079         return -NVL_BAD_ARGS;
2080     }
2081 
2082     *return_device = NULL;
2083 
2084     device = nvswitch_os_malloc(sizeof(*device));
2085     if (NULL == device)
2086     {
2087         NVSWITCH_PRINT(device, ERROR,
2088             "nvswitch_os_malloc during device creation failed!\n");
2089         return -NVL_NO_MEM;
2090     }
2091     nvswitch_os_memset(device, 0, sizeof(*device));
2092 
2093     nvswitch_os_snprintf(device->name, sizeof(device->name),
2094          NVSWITCH_DEVICE_NAME "%d", os_instance);
2095 
2096     coreDev = nvswitch_os_malloc(sizeof(*coreDev));
2097     if (NULL == coreDev)
2098     {
2099         NVSWITCH_PRINT(device, ERROR,
2100             "nvswitch_os_malloc during device creation failed!\n");
2101 
2102         retval = -NVL_NO_MEM;
2103         goto nvlink_lib_register_device_fail;
2104     }
2105     nvswitch_os_memset(coreDev, 0, sizeof(*coreDev));
2106 
2107     coreDev->driverName =
2108         nvswitch_os_malloc(sizeof(NVSWITCH_DRIVER_NAME));
2109     if (coreDev->driverName == NULL)
2110     {
2111         NVSWITCH_PRINT(device, ERROR,
2112             "nvswitch_os_malloc during device creation failed!\n");
2113 
2114         retval = -NVL_NO_MEM;
2115         goto nvlink_lib_register_device_fail;
2116     }
2117     nvswitch_os_memcpy(coreDev->driverName, NVSWITCH_DRIVER_NAME,
2118                        sizeof(NVSWITCH_DRIVER_NAME));
2119 
2120     device->os_handle   = os_handle;
2121     device->os_instance = os_instance;
2122 
2123     device->nvlink_device             = coreDev;
2124     device->nvlink_device->deviceName = device->name;
2125     device->nvlink_device->uuid = NULL; // No UUID support for switch
2126 
2127     device->nvlink_device->pciInfo.domain      = pci_domain;
2128     device->nvlink_device->pciInfo.bus         = pci_bus;
2129     device->nvlink_device->pciInfo.device      = pci_device;
2130     device->nvlink_device->pciInfo.function    = pci_func;
2131     device->nvlink_device->pciInfo.pciDeviceId = pci_device_id;
2132 
2133     // nvlink_device has a back pointer to nvswitch_device
2134     device->nvlink_device->pDevInfo = device;
2135     device->nvlink_device->type = NVLINK_DEVICE_TYPE_NVSWITCH;
2136 
2137     //
2138     // Initialize the Fabric State
2139     //
2140     device->fm_timeout = NVSWITCH_DEFAULT_FM_HEARTBEAT_TIMEOUT_MSEC;
2141     device->fabric_state_sequence_number = 0;
2142     device->driver_fabric_state = NVSWITCH_DRIVER_FABRIC_STATE_STANDBY;
2143     device->device_fabric_state = NVSWITCH_DEVICE_FABRIC_STATE_STANDBY;
2144     device->device_blacklist_reason = NVSWITCH_DEVICE_BLACKLIST_REASON_NONE;
2145 
2146     //
2147     // Initialize HAL connectivity as early as possible so that other lib
2148     // interfaces can work.
2149     //
2150     retval = _nvswitch_setup_hal(device, device->nvlink_device->pciInfo.pciDeviceId);
2151     if (retval != NVL_SUCCESS)
2152     {
2153         goto nvlink_lib_register_device_fail;
2154     }
2155 
2156     //
2157     // Initialize regkeys as early as possible so that most routines can take
2158     // advantage of them.
2159     //
2160     _nvswitch_init_device_regkeys(device);
2161 
2162     // After regkeys have been set then only set the enableALI field.
2163     device->nvlink_device->enableALI = (device->regkeys.link_training_mode ==
2164                         NV_SWITCH_REGKEY_LINK_TRAINING_SELECT_ALI) ? NV_TRUE:NV_FALSE;
2165 
2166     retval = nvlink_lib_register_device(device->nvlink_device);
2167     if (NVL_SUCCESS != retval)
2168     {
2169         NVSWITCH_PRINT(device, ERROR,
2170             "nvlinklib register device failed!\n");
2171         goto nvlink_lib_register_device_fail;
2172     }
2173 
2174     *return_device = device;
2175 
2176     NVSWITCH_PRINT(device, SETUP,
2177         "Successfully registered with nvlinkcore\n");
2178 
2179     return retval;
2180 
2181 nvlink_lib_register_device_fail:
2182 
2183     if (NULL != coreDev)
2184     {
2185         nvswitch_os_free(coreDev->driverName);
2186         nvswitch_os_free(coreDev);
2187     }
2188 
2189     if (NULL != device)
2190         nvswitch_os_free(device);
2191 
2192     return retval;
2193 }
2194 
2195 void
2196 nvswitch_lib_unregister_device
2197 (
2198     nvswitch_device *device
2199 )
2200 {
2201     if (!NVSWITCH_IS_DEVICE_VALID(device))
2202     {
2203         NVSWITCH_ASSERT(0);
2204         return;
2205     }
2206 
2207     nvlink_lib_unregister_device(device->nvlink_device);
2208 
2209     nvswitch_os_free(device->nvlink_device->driverName);
2210     nvswitch_os_free(device->nvlink_device);
2211     nvswitch_os_free(device);
2212 
2213     return;
2214 }
2215 
2216 /*!
2217  * @brief: Gets the mask of valid I2C ports on the
2218  *         Device.
2219  */
2220 NvlStatus
2221 nvswitch_lib_get_valid_ports_mask
2222 (
2223     nvswitch_device *device,
2224     NvU32 *validPortsMask
2225 )
2226 {
2227     NvU32 port_info;
2228     NvU32 i;
2229     NvU32 ports_mask = 0;
2230     NvBool is_i2c_access_allowed;
2231     NvBool is_port_allowed;
2232 
2233     if (!NVSWITCH_IS_DEVICE_VALID(device) ||
2234         (validPortsMask == NULL))
2235     {
2236         return -NVL_BAD_ARGS;
2237     }
2238 
2239     is_i2c_access_allowed = (device->regkeys.i2c_access_control ==
2240                              NV_SWITCH_REGKEY_I2C_ACCESS_CONTROL_ENABLE) ?
2241                                 NV_TRUE : NV_FALSE;
2242 
2243     for (i = 0; i < NVSWITCH_MAX_I2C_PORTS; i++)
2244     {
2245         port_info = nvswitch_i2c_get_port_info(device, i);
2246 
2247         is_port_allowed = is_i2c_access_allowed ? NV_TRUE :
2248                               FLD_TEST_DRF(_I2C, _PORTINFO, _ACCESS_ALLOWED, _TRUE,
2249                                            port_info);
2250 
2251         if (is_port_allowed &&
2252             FLD_TEST_DRF(_I2C, _PORTINFO, _DEFINED, _PRESENT, port_info))
2253         {
2254             ports_mask |= NVBIT(i);
2255         }
2256     }
2257 
2258     *validPortsMask = ports_mask;
2259     return NVL_SUCCESS;
2260 }
2261 
2262 /*!
2263  * @brief: Returns if the I2C transactions are supported.
2264  */
2265 NvBool
2266 nvswitch_lib_is_i2c_supported
2267 (
2268     nvswitch_device *device
2269 )
2270 {
2271     if (!NVSWITCH_IS_DEVICE_VALID(device))
2272     {
2273         NVSWITCH_ASSERT(0);
2274         return NV_FALSE;
2275     }
2276 
2277     return nvswitch_is_i2c_supported(device);
2278 }
2279 
2280 static NvlStatus
2281 _nvswitch_perform_i2c_transfer
2282 (
2283     nvswitch_device *device,
2284     NvU32 client,
2285     NvU8 type,
2286     NvU16 addr,
2287     NvU8 port,
2288     NvU8 cmd,
2289     NvU32 msgLength,
2290     NvU8 *pData
2291 )
2292 {
2293     NvlStatus status;
2294     NvU16 deviceAddr;
2295     NvU32 speedMode;
2296     NvBool bIsRead = NV_FALSE;
2297     NvU32 flags = 0;
2298     NVSWITCH_CTRL_I2C_INDEXED_PARAMS i2c_params = {0};
2299     NvBool is_i2c_access_allowed;
2300 
2301     if (!nvswitch_os_is_admin())
2302     {
2303         return -NVL_ERR_INSUFFICIENT_PERMISSIONS;
2304     }
2305 
2306     is_i2c_access_allowed = (device->regkeys.i2c_access_control ==
2307                              NV_SWITCH_REGKEY_I2C_ACCESS_CONTROL_ENABLE) ?
2308                                 NV_TRUE : NV_FALSE;
2309 
2310     //
2311     // The address needs to be shifted by 1,
2312     // See NVSWITCH_CTRL_I2C_INDEXED_PARAMS
2313     //
2314     deviceAddr = addr << 1;
2315     speedMode  = device->pI2c->Ports[port].defaultSpeedMode;
2316     flags      = DRF_DEF(SWITCH_CTRL, _I2C_FLAGS, _START, _SEND)              |
2317                  DRF_DEF(SWITCH_CTRL, _I2C_FLAGS, _STOP, _SEND)               |
2318                  DRF_DEF(SWITCH_CTRL, _I2C_FLAGS, _ADDRESS_MODE, _7BIT)       |
2319                  DRF_DEF(SWITCH_CTRL, _I2C_FLAGS, _FLAVOR, _HW)               |
2320                  DRF_DEF(SWITCH_CTRL, _I2C_FLAGS, _BLOCK_PROTOCOL, _DISABLED) |
2321                  DRF_DEF(SWITCH_CTRL, _I2C_FLAGS, _TRANSACTION_MODE, _NORMAL);
2322 
2323     switch (speedMode)
2324     {
2325         case NVSWITCH_I2C_SPEED_MODE_1000KHZ:
2326         {
2327             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _SPEED_MODE, _1000KHZ, flags);
2328             break;
2329         }
2330         case NVSWITCH_I2C_SPEED_MODE_400KHZ:
2331         {
2332             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _SPEED_MODE, _400KHZ, flags);
2333             break;
2334         }
2335         case NVSWITCH_I2C_SPEED_MODE_300KHZ:
2336         {
2337             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _SPEED_MODE, _300KHZ, flags);
2338             break;
2339         }
2340         case NVSWITCH_I2C_SPEED_MODE_200KHZ:
2341         {
2342             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _SPEED_MODE, _200KHZ, flags);
2343             break;
2344         }
2345         case NVSWITCH_I2C_SPEED_MODE_100KHZ:
2346         {
2347             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _SPEED_MODE, _100KHZ, flags);
2348             break;
2349         }
2350         default:
2351         {
2352             NVSWITCH_PRINT(device, ERROR, "Invalid I2C speed!\n");
2353             status = -NVL_BAD_ARGS;
2354             goto end;
2355         }
2356     }
2357 
2358     switch (type)
2359     {
2360         case NVSWITCH_I2C_CMD_READ:
2361             bIsRead = NV_TRUE;
2362             // Fall through
2363         case NVSWITCH_I2C_CMD_WRITE:
2364         {
2365             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _INDEX_LENGTH, _ZERO, flags);
2366             break;
2367         }
2368         case NVSWITCH_I2C_CMD_SMBUS_READ:
2369         {
2370             bIsRead = NV_TRUE;
2371             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _RESTART, _SEND, flags);
2372             // Fall through
2373         }
2374         case NVSWITCH_I2C_CMD_SMBUS_WRITE:
2375         {
2376             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _INDEX_LENGTH, _ONE, flags);
2377             break;
2378         }
2379         case NVSWITCH_I2C_CMD_SMBUS_QUICK_READ:
2380             bIsRead = NV_TRUE;
2381             // Fall through
2382         case NVSWITCH_I2C_CMD_SMBUS_QUICK_WRITE:
2383         {
2384             flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _INDEX_LENGTH, _ZERO, flags);
2385             msgLength = 0;
2386             break;
2387         }
2388         default:
2389         {
2390             NVSWITCH_PRINT(device, ERROR, "Invalid SMBUS protocol! Protocol not supported.\n");
2391             status = -NVL_BAD_ARGS;
2392             goto end;
2393         }
2394     }
2395 
2396     if (!is_i2c_access_allowed &&
2397         !nvswitch_i2c_is_device_access_allowed(device, port, deviceAddr, bIsRead))
2398     {
2399         return -NVL_BAD_ARGS;
2400     }
2401 
2402     if (msgLength > NVSWITCH_CTRL_I2C_MESSAGE_LENGTH_MAX)
2403     {
2404         NVSWITCH_PRINT(device, ERROR,
2405             "Length of buffer (0x%x bytes) provided larger than max (0x%x bytes)\n",
2406              msgLength, NVSWITCH_CTRL_I2C_MESSAGE_LENGTH_MAX);
2407         status = -NVL_BAD_ARGS;
2408         goto end;
2409     }
2410 
2411     if (bIsRead)
2412     {
2413         i2c_params.bIsRead = NV_TRUE;
2414     }
2415     else
2416     {
2417         flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _RESTART, _NONE, flags);
2418         nvswitch_os_memcpy(i2c_params.message, pData, msgLength);
2419     }
2420 
2421     if (FLD_TEST_DRF(SWITCH_CTRL, _I2C_FLAGS, _INDEX_LENGTH, _ONE, flags))
2422     {
2423         i2c_params.index[0] = cmd;
2424     }
2425 
2426     i2c_params.port     = port;
2427     i2c_params.address  = deviceAddr;
2428     i2c_params.acquirer = client;
2429     i2c_params.flags    = flags;
2430     i2c_params.messageLength = msgLength;
2431 
2432     status = nvswitch_ctrl_i2c_indexed(device, &i2c_params);
2433     if (status != NVL_SUCCESS)
2434     {
2435         NVSWITCH_PRINT(device, ERROR, "I2C transfer Failed!\n");
2436         goto end;
2437     }
2438 
2439     if (bIsRead)
2440     {
2441         nvswitch_os_memcpy(pData, i2c_params.message, msgLength);
2442     }
2443 
2444 end:
2445     return status;
2446 }
2447 
2448 /*!
2449  * @brief: Performs an I2C transaction.
2450  */
2451 NvlStatus
2452 nvswitch_lib_i2c_transfer
2453 (
2454     nvswitch_device *device,
2455     NvU32 port,
2456     NvU8 type,
2457     NvU8 addr,
2458     NvU8 command,
2459     NvU32 len,
2460     NvU8 *pData
2461 )
2462 {
2463     NvlStatus status;
2464     NvU32 port_info;
2465     NvBool is_i2c_access_allowed;
2466     NvBool is_port_allowed;
2467 
2468     if (!NVSWITCH_IS_DEVICE_VALID(device))
2469     {
2470         NVSWITCH_ASSERT(0);
2471         return -NVL_ERR_INVALID_STATE;
2472     }
2473 
2474     port_info = nvswitch_i2c_get_port_info(device, port);
2475 
2476     is_i2c_access_allowed = (device->regkeys.i2c_access_control ==
2477                              NV_SWITCH_REGKEY_I2C_ACCESS_CONTROL_ENABLE) ?
2478                                 NV_TRUE : NV_FALSE;
2479     is_port_allowed = is_i2c_access_allowed ? NV_TRUE :
2480                           FLD_TEST_DRF(_I2C, _PORTINFO, _ACCESS_ALLOWED, _TRUE,
2481                                        port_info);
2482 
2483     if (!is_port_allowed ||
2484         !FLD_TEST_DRF(_I2C, _PORTINFO, _DEFINED, _PRESENT, port_info))
2485     {
2486         NVSWITCH_PRINT(device, INFO,
2487             "%s: Invalid port access %d.\n",
2488             __FUNCTION__, port);
2489         return (-NVL_BAD_ARGS);
2490     }
2491 
2492     status = _nvswitch_perform_i2c_transfer(device, NVSWITCH_I2C_ACQUIRER_EXTERNAL,
2493                                             type, (NvU16)addr, port, command, len, pData);
2494     if (status != NVL_SUCCESS)
2495     {
2496         NVSWITCH_PRINT(device, ERROR, "I2C transaction failed!\n");
2497         return status;
2498     }
2499 
2500     return NVL_SUCCESS;
2501 }
2502 
2503 void
2504 nvswitch_timeout_create
2505 (
2506     NvU64   timeout_ns,
2507     NVSWITCH_TIMEOUT *time
2508 )
2509 {
2510     NvU64   time_current;
2511 
2512     time_current = nvswitch_os_get_platform_time();
2513     time->timeout_ns = time_current + timeout_ns;
2514 }
2515 
2516 NvBool
2517 nvswitch_timeout_check
2518 (
2519     NVSWITCH_TIMEOUT *time
2520 )
2521 {
2522     NvU64   time_current;
2523 
2524     time_current = nvswitch_os_get_platform_time();
2525     return (time->timeout_ns <= time_current);
2526 }
2527 
2528 NvlStatus
2529 nvswitch_task_create
2530 (
2531     nvswitch_device *device,
2532     void (*task_fn)(nvswitch_device *device),
2533     NvU64 period_nsec,
2534     NvU32 flags
2535 )
2536 {
2537     NVSWITCH_TASK_TYPE *task;
2538     task = nvswitch_os_malloc(sizeof(NVSWITCH_TASK_TYPE));
2539 
2540     if (task == NULL)
2541     {
2542         NVSWITCH_PRINT(device, ERROR,
2543             "%s: Unable to allocate task.\n",
2544             __FUNCTION__);
2545         return -NVL_NO_MEM;
2546     }
2547     else
2548     {
2549         task->task_fn_devptr = task_fn;
2550         task->task_args = NULL;
2551         task->period_nsec = period_nsec;
2552         task->last_run_nsec = nvswitch_os_get_platform_time(); // Prevent deferred tasks from being run immediately
2553         task->flags = flags;
2554         task->prev = NULL;
2555         task->next = device->tasks;
2556         if (device->tasks != NULL)
2557         {
2558             device->tasks->prev = task;
2559         }
2560         device->tasks = task;
2561     }
2562 
2563     return NVL_SUCCESS;
2564 }
2565 
2566 NvlStatus
2567 nvswitch_task_create_args
2568 (
2569     nvswitch_device *device,
2570     void *fn_args,
2571     void (*task_fn)(nvswitch_device* device, void *fn_args),
2572     NvU64 period_nsec,
2573     NvU32 flags
2574 )
2575 {
2576     NVSWITCH_TASK_TYPE *task;
2577     task = nvswitch_os_malloc(sizeof(NVSWITCH_TASK_TYPE));
2578 
2579     flags = flags | NVSWITCH_TASK_TYPE_FLAGS_VOID_PTR_ARGS;  // ensure dispatcher always executes tasks passed through this function with args
2580 
2581     if (task == NULL)
2582     {
2583         NVSWITCH_PRINT(device, ERROR,
2584             "%s: Unable to allocate task.\n",
2585             __FUNCTION__);
2586         return -NVL_NO_MEM;
2587     }
2588     else
2589     {
2590         task->task_fn_vdptr = task_fn;
2591         task->task_args = fn_args;
2592         task->period_nsec = period_nsec;
2593         task->last_run_nsec = nvswitch_os_get_platform_time(); // Prevent deferred tasks from being run immediately
2594         task->flags = flags;
2595         task->prev = NULL;
2596         task->next = device->tasks;
2597         if (device->tasks != NULL)
2598         {
2599             device->tasks->prev = task;
2600         }
2601         device->tasks = task;
2602     }
2603 
2604     return NVL_SUCCESS;
2605 }
2606 
2607 void
2608 nvswitch_tasks_destroy
2609 (
2610     nvswitch_device *device
2611 )
2612 {
2613     NVSWITCH_TASK_TYPE *task = device->tasks;
2614     NVSWITCH_TASK_TYPE *next_task;
2615 
2616     device->tasks = NULL;
2617 
2618     while (task)
2619     {
2620         next_task = task->next;
2621         nvswitch_os_free(task);
2622         task = next_task;
2623     }
2624 }
2625 
2626 void
2627 nvswitch_destroy_device_state
2628 (
2629     nvswitch_device *device
2630 )
2631 {
2632     device->hal.nvswitch_destroy_device_state(device);
2633 }
2634 
2635 static NvlStatus
2636 _nvswitch_ctrl_get_info
2637 (
2638     nvswitch_device *device,
2639     NVSWITCH_GET_INFO *p
2640 )
2641 {
2642     return device->hal.nvswitch_ctrl_get_info(device, p);
2643 }
2644 
2645 static NvlStatus
2646 _nvswitch_ctrl_get_nvlink_status
2647 (
2648     nvswitch_device *device,
2649     NVSWITCH_GET_NVLINK_STATUS_PARAMS *ret
2650 )
2651 {
2652     return device->hal.nvswitch_ctrl_get_nvlink_status(device, ret);
2653 }
2654 
2655 static NvlStatus
2656 _nvswitch_ctrl_get_counters
2657 (
2658     nvswitch_device *device,
2659     NVSWITCH_NVLINK_GET_COUNTERS_PARAMS *ret
2660 )
2661 {
2662     return device->hal.nvswitch_ctrl_get_counters(device, ret);
2663 }
2664 
2665 NvlStatus
2666 nvswitch_set_nport_port_config
2667 (
2668     nvswitch_device *device,
2669     NVSWITCH_SET_SWITCH_PORT_CONFIG *p
2670 )
2671 {
2672     return device->hal.nvswitch_set_nport_port_config(device, p);
2673 }
2674 
2675 static NvlStatus
2676 _nvswitch_ctrl_set_switch_port_config
2677 (
2678     nvswitch_device *device,
2679     NVSWITCH_SET_SWITCH_PORT_CONFIG *p
2680 )
2681 {
2682     return device->hal.nvswitch_ctrl_set_switch_port_config(device, p);
2683 }
2684 
2685 static NvlStatus
2686 _nvswitch_ctrl_get_ingress_request_table
2687 (
2688     nvswitch_device *device,
2689     NVSWITCH_GET_INGRESS_REQUEST_TABLE_PARAMS *params
2690 )
2691 {
2692     return device->hal.nvswitch_ctrl_get_ingress_request_table(device, params);
2693 }
2694 
2695 static NvlStatus
2696 _nvswitch_ctrl_set_ingress_request_table
2697 (
2698     nvswitch_device *device,
2699     NVSWITCH_SET_INGRESS_REQUEST_TABLE *p
2700 )
2701 {
2702     return device->hal.nvswitch_ctrl_set_ingress_request_table(device, p);
2703 }
2704 
2705 static NvlStatus
2706 _nvswitch_ctrl_set_ingress_request_valid
2707 (
2708     nvswitch_device *device,
2709     NVSWITCH_SET_INGRESS_REQUEST_VALID *p
2710 )
2711 {
2712     return device->hal.nvswitch_ctrl_set_ingress_request_valid(device, p);
2713 }
2714 
2715 static NvlStatus
2716 _nvswitch_ctrl_get_ingress_response_table
2717 (
2718     nvswitch_device *device,
2719     NVSWITCH_GET_INGRESS_RESPONSE_TABLE_PARAMS *params
2720 )
2721 {
2722     return device->hal.nvswitch_ctrl_get_ingress_response_table(device, params);
2723 }
2724 
2725 static NvlStatus
2726 _nvswitch_ctrl_set_ingress_response_table
2727 (
2728     nvswitch_device *device,
2729     NVSWITCH_SET_INGRESS_RESPONSE_TABLE *p
2730 )
2731 {
2732     return device->hal.nvswitch_ctrl_set_ingress_response_table(device, p);
2733 }
2734 
2735 static NvlStatus
2736 _nvswitch_ctrl_set_ganged_link_table
2737 (
2738     nvswitch_device *device,
2739     NVSWITCH_SET_GANGED_LINK_TABLE *p
2740 )
2741 {
2742     return device->hal.nvswitch_ctrl_set_ganged_link_table(device, p);
2743 }
2744 
2745 void
2746 nvswitch_init_npg_multicast
2747 (
2748     nvswitch_device *device
2749 )
2750 {
2751     return device->hal.nvswitch_init_npg_multicast(device);
2752 }
2753 
2754 void
2755 nvswitch_init_warm_reset
2756 (
2757     nvswitch_device *device
2758 )
2759 {
2760     return device->hal.nvswitch_init_warm_reset(device);
2761 }
2762 
2763 static NvlStatus
2764 _nvswitch_ctrl_set_remap_policy
2765 (
2766     nvswitch_device *device,
2767     NVSWITCH_SET_REMAP_POLICY *p
2768 )
2769 {
2770     return device->hal.nvswitch_ctrl_set_remap_policy(device, p);
2771 }
2772 
2773 static NvlStatus
2774 _nvswitch_ctrl_get_remap_policy
2775 (
2776     nvswitch_device *device,
2777     NVSWITCH_GET_REMAP_POLICY_PARAMS *params
2778 )
2779 {
2780     return device->hal.nvswitch_ctrl_get_remap_policy(device, params);
2781 }
2782 
2783 static NvlStatus
2784 _nvswitch_ctrl_set_remap_policy_valid
2785 (
2786     nvswitch_device *device,
2787     NVSWITCH_SET_REMAP_POLICY_VALID *p
2788 )
2789 {
2790     return device->hal.nvswitch_ctrl_set_remap_policy_valid(device, p);
2791 }
2792 
2793 static NvlStatus
2794 _nvswitch_ctrl_set_routing_id
2795 (
2796     nvswitch_device *device,
2797     NVSWITCH_SET_ROUTING_ID *p
2798 )
2799 {
2800     return device->hal.nvswitch_ctrl_set_routing_id(device, p);
2801 }
2802 
2803 static NvlStatus
2804 _nvswitch_ctrl_get_routing_id
2805 (
2806     nvswitch_device *device,
2807     NVSWITCH_GET_ROUTING_ID_PARAMS *params
2808 )
2809 {
2810     return device->hal.nvswitch_ctrl_get_routing_id(device, params);
2811 }
2812 
2813 static NvlStatus
2814 _nvswitch_ctrl_set_routing_id_valid
2815 (
2816     nvswitch_device *device,
2817     NVSWITCH_SET_ROUTING_ID_VALID *p
2818 )
2819 {
2820     return device->hal.nvswitch_ctrl_set_routing_id_valid(device, p);
2821 }
2822 
2823 static NvlStatus
2824 _nvswitch_ctrl_set_routing_lan
2825 (
2826     nvswitch_device *device,
2827     NVSWITCH_SET_ROUTING_LAN *p
2828 )
2829 {
2830     return device->hal.nvswitch_ctrl_set_routing_lan(device, p);
2831 }
2832 
2833 static NvlStatus
2834 _nvswitch_ctrl_get_routing_lan
2835 (
2836     nvswitch_device *device,
2837     NVSWITCH_GET_ROUTING_LAN_PARAMS *params
2838 )
2839 {
2840     return device->hal.nvswitch_ctrl_get_routing_lan(device, params);
2841 }
2842 
2843 static NvlStatus
2844 _nvswitch_ctrl_set_routing_lan_valid
2845 (
2846     nvswitch_device *device,
2847     NVSWITCH_SET_ROUTING_LAN_VALID *p
2848 )
2849 {
2850     return device->hal.nvswitch_ctrl_set_routing_lan_valid(device, p);
2851 }
2852 
2853 static NvlStatus
2854 _nvswitch_ctrl_get_internal_latency
2855 (
2856     nvswitch_device *device,
2857     NVSWITCH_GET_INTERNAL_LATENCY *p
2858 )
2859 {
2860     return device->hal.nvswitch_ctrl_get_internal_latency(device, p);
2861 }
2862 
2863 static NvlStatus
2864 _nvswitch_ctrl_get_nvlipt_counters
2865 (
2866     nvswitch_device *device,
2867     NVSWITCH_GET_NVLIPT_COUNTERS *p
2868 )
2869 {
2870     //
2871     // This control call is now deprecated.
2872     // New control call to fetch throughput counters is:
2873     // nvswitch_ctrl_get_throughput_counters
2874     //
2875     return -NVL_ERR_NOT_SUPPORTED;
2876 }
2877 
2878 static NvlStatus
2879 _nvswitch_ctrl_set_nvlipt_counter_config
2880 (
2881     nvswitch_device *device,
2882     NVSWITCH_SET_NVLIPT_COUNTER_CONFIG *p
2883 )
2884 {
2885     //
2886     // This control call is now deprecated.
2887     // New control call to fetch throughput counters is:
2888     // nvswitch_ctrl_get_throughput_counters_lr10
2889     //
2890     // Setting counter config is not allowed on these
2891     // non-configurable counters. These counters are
2892     // expected to be used by monitoring clients.
2893     //
2894     return -NVL_ERR_NOT_SUPPORTED;
2895 }
2896 
2897 static NvlStatus
2898 _nvswitch_ctrl_get_nvlipt_counter_config
2899 (
2900     nvswitch_device *device,
2901     NVSWITCH_GET_NVLIPT_COUNTER_CONFIG *p
2902 )
2903 {
2904     //
2905     // This control call is now deprecated.
2906     // New control call to fetch throughput counters is:
2907     // nvswitch_ctrl_get_throughput_counters_lr10
2908     //
2909     // Getting counter config is useful if counters are
2910     // configurable. These counters are not configurable
2911     // and are expected to be used by monitoring clients.
2912     //
2913     return -NVL_ERR_NOT_SUPPORTED;
2914 }
2915 
2916 static NvlStatus
2917 _nvswitch_ctrl_register_read
2918 (
2919     nvswitch_device *device,
2920     NVSWITCH_REGISTER_READ *p
2921 )
2922 {
2923     return device->hal.nvswitch_ctrl_register_read(device, p);
2924 }
2925 
2926 static NvlStatus
2927 _nvswitch_ctrl_register_write
2928 (
2929     nvswitch_device *device,
2930     NVSWITCH_REGISTER_WRITE *p
2931 )
2932 {
2933     return device->hal.nvswitch_ctrl_register_write(device, p);
2934 }
2935 
2936 NvU32
2937 nvswitch_i2c_get_port_info
2938 (
2939     nvswitch_device *device,
2940     NvU32 port
2941 )
2942 {
2943     return device->hal.nvswitch_i2c_get_port_info(device, port);
2944 }
2945 
2946 NvlStatus
2947 nvswitch_ctrl_i2c_indexed
2948 (
2949     nvswitch_device *device,
2950     NVSWITCH_CTRL_I2C_INDEXED_PARAMS *pParams
2951 )
2952 {
2953     return device->hal.nvswitch_ctrl_i2c_indexed(device, pParams);
2954 }
2955 
2956 static NvlStatus
2957 _nvswitch_ctrl_therm_read_temperature
2958 (
2959     nvswitch_device *device,
2960     NVSWITCH_CTRL_GET_TEMPERATURE_PARAMS *info
2961 )
2962 {
2963     return device->hal.nvswitch_ctrl_therm_read_temperature(device, info);
2964 }
2965 
2966 static NvlStatus
2967 _nvswitch_ctrl_get_bios_info
2968 (
2969     nvswitch_device *device,
2970     NVSWITCH_GET_BIOS_INFO_PARAMS *p
2971 )
2972 {
2973     return device->hal.nvswitch_ctrl_get_bios_info(device, p);
2974 }
2975 
2976 static NvlStatus
2977 _nvswitch_ctrl_get_inforom_version
2978 (
2979     nvswitch_device *device,
2980     NVSWITCH_GET_INFOROM_VERSION_PARAMS *p
2981 )
2982 {
2983     return device->hal.nvswitch_ctrl_get_inforom_version(device, p);
2984 }
2985 
2986 NvlStatus
2987 nvswitch_ctrl_set_latency_bins
2988 (
2989     nvswitch_device *device,
2990     NVSWITCH_SET_LATENCY_BINS *p
2991 )
2992 {
2993     return device->hal.nvswitch_ctrl_set_latency_bins(device, p);
2994 }
2995 
2996 static NvlStatus
2997 _nvswitch_ctrl_get_ingress_reqlinkid
2998 (
2999     nvswitch_device *device,
3000     NVSWITCH_GET_INGRESS_REQLINKID_PARAMS *params
3001 )
3002 {
3003     return device->hal.nvswitch_ctrl_get_ingress_reqlinkid(device, params);
3004 }
3005 
3006 NvlStatus
3007 nvswitch_ctrl_get_throughput_counters
3008 (
3009     nvswitch_device *device,
3010     NVSWITCH_GET_THROUGHPUT_COUNTERS_PARAMS *p
3011 )
3012 {
3013     return device->hal.nvswitch_ctrl_get_throughput_counters(device, p);
3014 }
3015 
3016 static NvlStatus
3017 _nvswitch_ctrl_unregister_link
3018 (
3019     nvswitch_device *device,
3020     NVSWITCH_UNREGISTER_LINK_PARAMS *params
3021 )
3022 {
3023     nvlink_link *link = nvswitch_get_link(device, (NvU8)params->portNum);
3024 
3025     if (link == NULL)
3026     {
3027         return -NVL_BAD_ARGS;
3028     }
3029 
3030     // With ALI in FW, links can be unregistered while Active
3031     if (!device->nvlink_device->enableALI)
3032     {
3033 
3034     if (device->hal.nvswitch_is_link_in_use(device, params->portNum))
3035     {
3036         return -NVL_ERR_STATE_IN_USE;
3037     }
3038 
3039     }
3040 
3041     nvlink_lib_unregister_link(link);
3042     nvswitch_destroy_link(link);
3043 
3044     return NVL_SUCCESS;
3045 }
3046 
3047 static NvlStatus
3048 _nvswitch_ctrl_acquire_capability
3049 (
3050     nvswitch_device *device,
3051     NVSWITCH_ACQUIRE_CAPABILITY_PARAMS *params,
3052     void *osPrivate
3053 )
3054 {
3055     return nvswitch_os_acquire_fabric_mgmt_cap(osPrivate,
3056                                                params->capDescriptor);
3057 }
3058 
3059 static NvlStatus
3060 _nvswitch_ctrl_reset_and_drain_links
3061 (
3062     nvswitch_device *device,
3063     NVSWITCH_RESET_AND_DRAIN_LINKS_PARAMS *params
3064 )
3065 {
3066     return device->hal.nvswitch_reset_and_drain_links(device, params->linkMask);
3067 }
3068 
3069 static NvlStatus
3070 _nvswitch_ctrl_get_fom_values
3071 (
3072     nvswitch_device *device,
3073     NVSWITCH_GET_FOM_VALUES_PARAMS *ret
3074 )
3075 {
3076     return device->hal.nvswitch_ctrl_get_fom_values(device, ret);
3077 }
3078 
3079 static NvlStatus
3080 _nvswitch_ctrl_get_nvlink_ecc_errors
3081 (
3082     nvswitch_device *device,
3083     NVSWITCH_GET_NVLINK_ECC_ERRORS_PARAMS *params
3084 )
3085 {
3086     return device->hal.nvswitch_get_nvlink_ecc_errors(device, params);
3087 }
3088 
3089 static NvlStatus
3090 _nvswitch_ctrl_set_mc_rid_table
3091 (
3092     nvswitch_device *device,
3093     NVSWITCH_SET_MC_RID_TABLE_PARAMS *p
3094 )
3095 {
3096     return device->hal.nvswitch_ctrl_set_mc_rid_table(device, p);
3097 }
3098 
3099 static NvlStatus
3100 _nvswitch_ctrl_get_mc_rid_table
3101 (
3102     nvswitch_device *device,
3103     NVSWITCH_GET_MC_RID_TABLE_PARAMS *p
3104 )
3105 {
3106     return device->hal.nvswitch_ctrl_get_mc_rid_table(device, p);
3107 }
3108 
3109 static NvlStatus
3110 _nvswitch_ctrl_set_residency_bins
3111 (
3112     nvswitch_device *device,
3113     NVSWITCH_SET_RESIDENCY_BINS *p
3114 )
3115 {
3116     return device->hal.nvswitch_ctrl_set_residency_bins(device, p);
3117 }
3118 
3119 static NvlStatus
3120 _nvswitch_ctrl_get_residency_bins
3121 (
3122     nvswitch_device *device,
3123     NVSWITCH_GET_RESIDENCY_BINS *p
3124 )
3125 {
3126     return device->hal.nvswitch_ctrl_get_residency_bins(device, p);
3127 }
3128 
3129 static NvlStatus
3130 _nvswitch_ctrl_get_rb_stall_busy
3131 (
3132     nvswitch_device *device,
3133     NVSWITCH_GET_RB_STALL_BUSY *p
3134 )
3135 {
3136     return device->hal.nvswitch_ctrl_get_rb_stall_busy(device, p);
3137 }
3138 
3139 NvlStatus
3140 nvswitch_ctrl_get_multicast_id_error_vector
3141 (
3142     nvswitch_device *device,
3143     NVSWITCH_GET_MULTICAST_ID_ERROR_VECTOR *p
3144 )
3145 {
3146     return device->hal.nvswitch_ctrl_get_multicast_id_error_vector(device, p);
3147 }
3148 
3149 NvlStatus
3150 nvswitch_ctrl_clear_multicast_id_error_vector
3151 (
3152     nvswitch_device *device,
3153     NVSWITCH_CLEAR_MULTICAST_ID_ERROR_VECTOR *p
3154 )
3155 {
3156     return device->hal.nvswitch_ctrl_clear_multicast_id_error_vector(device, p);
3157 }
3158 
3159 static NvlStatus
3160 _nvswitch_ctrl_inband_send_data
3161 (
3162     nvswitch_device *device,
3163     NVSWITCH_INBAND_SEND_DATA_PARAMS *p
3164 )
3165 {
3166     return device->hal.nvswitch_ctrl_inband_send_data(device, p);
3167 }
3168 
3169 static NvlStatus
3170 _nvswitch_ctrl_inband_read_data
3171 (
3172     nvswitch_device *device,
3173     NVSWITCH_INBAND_READ_DATA_PARAMS *p
3174 )
3175 {
3176     return device->hal.nvswitch_ctrl_inband_read_data(device, p);
3177 }
3178 
3179 static NvlStatus
3180 _nvswitch_ctrl_inband_flush_data
3181 (
3182     nvswitch_device *device,
3183     NVSWITCH_INBAND_FLUSH_DATA_PARAMS *p
3184 )
3185 {
3186     NvU32 i;
3187     NvU64 enabledLinkMask;
3188 
3189     if (p->linkMask == 0)
3190     {
3191         NVSWITCH_PRINT(device, ERROR, "Nothing to clear\n");
3192         return NVL_SUCCESS;
3193     }
3194 
3195     enabledLinkMask = nvswitch_get_enabled_link_mask(device);
3196 
3197     FOR_EACH_INDEX_IN_MASK(64, i, p->linkMask)
3198     {
3199          if (nvswitch_is_link_valid(device, i) &&
3200              (enabledLinkMask & NVBIT64(i)))
3201          {
3202               //
3203               // Flush is expected to clear both persistent and non-persistent
3204               // list. FM does flush when it wants to drop (ignore) all pending
3205               // messages w/o any NACKs.
3206               //
3207               _nvswitch_inband_clear_lists(device, i,
3208                                            NV_FALSE /* Nack */,
3209                                            NV_FALSE /* Non-persistent only */);
3210          }
3211     }
3212     FOR_EACH_INDEX_IN_MASK_END;
3213 
3214     return NVL_SUCCESS;
3215 }
3216 
3217 static NvlStatus
3218 _nvswitch_ctrl_inband_pending_data_stats
3219 (
3220     nvswitch_device *device,
3221     NVSWITCH_INBAND_PENDING_DATA_STATS_PARAMS *p
3222 )
3223 {
3224     NvU32 link_num;
3225     NvU64 enabledLinkMask, persistent_mask = 0, nonpersistent_mask = 0;
3226 
3227     enabledLinkMask = nvswitch_get_enabled_link_mask(device);
3228 
3229     for (link_num = 0; link_num < nvswitch_get_num_links(device); link_num++)
3230     {
3231          if (nvswitch_is_link_valid(device, link_num) &&
3232              (enabledLinkMask & NVBIT64(link_num)))
3233          {
3234               if (!nvListIsEmpty(&device->link[link_num].inbandData.persistent_list))
3235               {
3236                   persistent_mask |= NVBIT64(link_num);
3237               }
3238 
3239               if (!nvListIsEmpty(&device->link[link_num].inbandData.nonpersistent_list))
3240               {
3241                   nonpersistent_mask |= NVBIT64(link_num);
3242               }
3243          }
3244     }
3245 
3246     if (persistent_mask > 0)
3247     {
3248         p->linkMask = persistent_mask;
3249     }
3250     else
3251     {
3252         p->linkMask = nonpersistent_mask;
3253     }
3254 
3255     return NVL_SUCCESS;
3256 }
3257 
3258 static NvlStatus
3259 _nvswitch_ctrl_get_board_part_number
3260 (
3261     nvswitch_device *device,
3262     NVSWITCH_GET_BOARD_PART_NUMBER_VECTOR *p
3263 )
3264 {
3265     if (IS_RTLSIM(device) || IS_EMULATION(device) || IS_FMODEL(device))
3266     {
3267         NVSWITCH_PRINT(device, INFO,
3268         "%s: Skipping retrieval of board part number on FSF\n",
3269             __FUNCTION__);
3270 
3271         nvswitch_os_memset(p, 0, sizeof(NVSWITCH_GET_BOARD_PART_NUMBER_VECTOR));
3272 
3273        return NVL_SUCCESS;
3274     }
3275     else
3276     {
3277         if (!nvswitch_is_inforom_supported(device))
3278         {
3279             NVSWITCH_PRINT(device, ERROR, "InfoROM is not supported\n");
3280             return -NVL_ERR_NOT_SUPPORTED;
3281         }
3282 
3283         return device->hal.nvswitch_ctrl_get_board_part_number(device, p);
3284     }
3285 }
3286 
3287 static NvlStatus
3288 _nvswitch_ctrl_i2c_smbus_command
3289 (
3290     nvswitch_device *device,
3291     NVSWITCH_I2C_SMBUS_COMMAND_PARAMS *pParams
3292 )
3293 {
3294     NvU32 port_info;
3295     NvU32 port = pParams->port;
3296     NvU8 msgLen;
3297     NvU8 cmd;
3298     NvU16 addr;
3299     NvU8 cmdType;
3300     NvU8 *pData;
3301     NvBool is_i2c_access_allowed;
3302     NvBool is_port_allowed;
3303 
3304     port_info = nvswitch_i2c_get_port_info(device, port);
3305 
3306     is_i2c_access_allowed = (device->regkeys.i2c_access_control ==
3307                              NV_SWITCH_REGKEY_I2C_ACCESS_CONTROL_ENABLE) ?
3308                                 NV_TRUE : NV_FALSE;
3309     is_port_allowed = is_i2c_access_allowed ? NV_TRUE :
3310                           FLD_TEST_DRF(_I2C, _PORTINFO, _ACCESS_ALLOWED, _TRUE,
3311                                        port_info);
3312 
3313     if (!is_port_allowed ||
3314         !FLD_TEST_DRF(_I2C, _PORTINFO, _DEFINED, _PRESENT, port_info))
3315     {
3316         NVSWITCH_PRINT(device, ERROR, "Invalid port access %d.\n", port);
3317         return NVL_BAD_ARGS;
3318     }
3319 
3320     addr = pParams->deviceAddr;
3321 
3322     switch (pParams->cmdType)
3323     {
3324         case NVSWITCH_I2C_SMBUS_CMD_QUICK:
3325         {
3326             cmd = 0;
3327             msgLen = 0;
3328             cmdType = pParams->bRead ?
3329                           NVSWITCH_I2C_CMD_SMBUS_QUICK_READ :
3330                           NVSWITCH_I2C_CMD_SMBUS_QUICK_WRITE;
3331             pData = NULL;
3332             break;
3333         }
3334         case NVSWITCH_I2C_SMBUS_CMD_BYTE:
3335         {
3336             cmd = 0;
3337             msgLen = 1;
3338             cmdType = pParams->bRead ?
3339                           NVSWITCH_I2C_CMD_READ :
3340                           NVSWITCH_I2C_CMD_WRITE;
3341             pData = (NvU8 *)&pParams->transactionData.smbusByte.message;
3342             break;
3343         }
3344         case NVSWITCH_I2C_SMBUS_CMD_BYTE_DATA:
3345         {
3346             msgLen = 1;
3347             cmd = pParams->transactionData.smbusByteData.cmd;
3348             cmdType = pParams->bRead ?
3349                           NVSWITCH_I2C_CMD_SMBUS_READ :
3350                           NVSWITCH_I2C_CMD_SMBUS_WRITE;
3351             pData = (NvU8 *)&pParams->transactionData.smbusByteData.message;
3352             break;
3353         }
3354         case NVSWITCH_I2C_SMBUS_CMD_WORD_DATA:
3355         {
3356             msgLen = 2;
3357             cmd = pParams->transactionData.smbusWordData.cmd;
3358             cmdType = pParams->bRead ?
3359                           NVSWITCH_I2C_CMD_SMBUS_READ :
3360                           NVSWITCH_I2C_CMD_SMBUS_WRITE;
3361             pData = (NvU8 *)&pParams->transactionData.smbusWordData.message;
3362             break;
3363         }
3364         default:
3365         {
3366             NVSWITCH_PRINT(device, ERROR, "Invalid Smbus command: %d.\n", port);
3367             return NVL_BAD_ARGS;
3368         }
3369     }
3370 
3371     return _nvswitch_perform_i2c_transfer(device, NVSWITCH_I2C_ACQUIRER_IOCTL,
3372                                           cmdType, addr, port, cmd, msgLen, pData);
3373 }
3374 
3375 NvBool
3376 nvswitch_does_link_need_termination_enabled
3377 (
3378     nvswitch_device *device,
3379     nvlink_link *link
3380 )
3381 {
3382     return device->hal.nvswitch_does_link_need_termination_enabled(device, link);
3383 }
3384 
3385 NvlStatus
3386 nvswitch_link_termination_setup
3387 (
3388     nvswitch_device *device,
3389     nvlink_link* link
3390 )
3391 {
3392     return device->hal.nvswitch_link_termination_setup(device, link);
3393 }
3394 
3395 static NvlStatus
3396 _nvswitch_ctrl_get_inforom_nvlink_max_correctable_error_rate
3397 (
3398     nvswitch_device *device,
3399     NVSWITCH_GET_NVLINK_MAX_CORRECTABLE_ERROR_RATES_PARAMS *params
3400 )
3401 {
3402     return nvswitch_inforom_nvlink_get_max_correctable_error_rate(device, params);
3403 }
3404 
3405 static NvlStatus
3406 _nvswitch_ctrl_get_inforom_nvlink_errors
3407 (
3408     nvswitch_device *device,
3409     NVSWITCH_GET_NVLINK_ERROR_COUNTS_PARAMS *params
3410 )
3411 {
3412     return nvswitch_inforom_nvlink_get_errors(device, params);
3413 }
3414 
3415 static NvlStatus
3416 _nvswitch_ctrl_get_inforom_ecc_errors
3417 (
3418     nvswitch_device *device,
3419     NVSWITCH_GET_ECC_ERROR_COUNTS_PARAMS *params
3420 )
3421 {
3422     return nvswitch_inforom_ecc_get_errors(device, params);
3423 }
3424 
3425 static NvlStatus
3426 _nvswitch_ctrl_get_inforom_bbx_sxid
3427 (
3428     nvswitch_device *device,
3429     NVSWITCH_GET_SXIDS_PARAMS *params
3430 )
3431 {
3432     return nvswitch_inforom_bbx_get_sxid(device, params);
3433 }
3434 
3435 static NvlStatus
3436 _nvswitch_ctrl_get_nvlink_lp_counters
3437 (
3438     nvswitch_device *device,
3439     NVSWITCH_GET_NVLINK_LP_COUNTERS_PARAMS *params
3440 )
3441 {
3442     return device->hal.nvswitch_ctrl_get_nvlink_lp_counters(device, params);
3443 }
3444 
3445 static NvlStatus
3446 _nvswitch_ctrl_get_sw_info
3447 (
3448     nvswitch_device *device,
3449     NVSWITCH_GET_SW_INFO_PARAMS *params
3450 )
3451 {
3452     return device->hal.nvswitch_ctrl_get_sw_info(device, params);
3453 }
3454 
3455 static NvlStatus
3456 _nvswitch_lib_validate_privileged_ctrl
3457 (
3458     void *osPrivate,
3459     NvU64 flags
3460 )
3461 {
3462     if (flags & NVSWITCH_DEV_CMD_CHECK_ADMIN)
3463     {
3464         if (nvswitch_os_is_admin())
3465         {
3466             return NVL_SUCCESS;
3467         }
3468     }
3469 
3470     if (flags & NVSWITCH_DEV_CMD_CHECK_FM)
3471     {
3472         if (nvswitch_os_is_fabric_manager(osPrivate))
3473         {
3474             return NVL_SUCCESS;
3475         }
3476     }
3477 
3478     return -NVL_ERR_INSUFFICIENT_PERMISSIONS;
3479 }
3480 
3481 /*
3482  * @Brief : Copy the data from the persistant or nonpersistant list
3483  *
3484  * @Description :
3485  *
3486  * @param[in] device            NvSwitch device to contain this link
3487  * @param[out] data             Destination Data
3488  * @param[in] linkId            link number of the link
3489  * @param[out] dataSize         Size of data copied
3490  *
3491  * @returns                     NVL_SUCCESS if action succeeded,
3492  *                              -NVL_NOT_FOUND if link doesnt have data
3493  */
3494 NvlStatus
3495 nvswitch_inband_read_data
3496 (
3497     nvswitch_device *device,
3498     NvU8 *dest,
3499     NvU32 linkId,
3500     NvU32 *dataSize
3501 )
3502 {
3503     nvswitch_inband_data_list *curr = NULL;
3504     NVListRec *list;
3505 
3506     if (nvListIsEmpty(&device->link[linkId].inbandData.persistent_list) &&
3507         nvListIsEmpty(&device->link[linkId].inbandData.nonpersistent_list))
3508     {
3509         NVSWITCH_PRINT(device, ERROR, "%s: LinkId %d doesnt have any data to send\n",
3510                          __FUNCTION__, linkId);
3511         *dataSize = 0;
3512         return -NVL_NOT_FOUND;
3513     }
3514 
3515     list = nvListIsEmpty(&device->link[linkId].inbandData.persistent_list) ?
3516                          &device->link[linkId].inbandData.nonpersistent_list :
3517                          &device->link[linkId].inbandData.persistent_list;
3518 
3519     nvListForEachEntry(curr, list, entry)
3520     {
3521          *dataSize = curr->dataSize;
3522          nvswitch_os_memcpy(dest, curr->data, curr->dataSize);
3523          nvListDel(&curr->entry);
3524          nvswitch_os_free(curr);
3525          break;
3526     }
3527 
3528     return NVL_SUCCESS;
3529 }
3530 
3531 /*
3532  * @Brief : Returns NV_TRUE if the given inband msg
3533  *          needs to go to persistant list
3534  *
3535  * @Description :
3536  *
3537  * @param[in] device            NvSwitch device to contain this link
3538  * @param[in] msghdr            Header to the message
3539  *
3540  */
3541 
3542 static NvBool
3543 nvswitch_is_message_persistent
3544 (
3545     nvswitch_device *device,
3546     nvlink_inband_msg_header_t *msghdr
3547 )
3548 {
3549     // We expect only one message per received data
3550     switch(msghdr->type)
3551     {
3552         case NVLINK_INBAND_MSG_TYPE_MC_TEAM_RELEASE_REQ:
3553             return NV_TRUE;
3554         default:
3555             return NV_FALSE;
3556     }
3557 }
3558 
3559 /*
3560  * @Brief : Moves the data into persistant or nonpersistant list
3561  *
3562  * @Description :
3563  *
3564  * @param[in] device            NvSwitch device to contain this link
3565  * @param[in] linkId            link number of the link
3566  *
3567  */
3568 void
3569 nvswitch_filter_messages
3570 (
3571     nvswitch_device *device,
3572     NvU32           linkId
3573 )
3574 {
3575     NvlStatus status;
3576     nvlink_inband_msg_header_t *msghdr = NULL;
3577     nvswitch_inband_data_list *msg = device->link[linkId].inbandData.message;
3578     NvU8   *buffer = device->link[linkId].inbandData.message->data;
3579     NVSWITCH_DRIVER_FABRIC_STATE driver_fabric_state = 0;
3580     NvBool bSendNackOrDrop = NV_FALSE;
3581 
3582     NVSWITCH_ASSERT(nvswitch_lib_read_fabric_state(device, NULL, NULL,
3583                                         &driver_fabric_state) == NVL_SUCCESS);
3584 
3585     msghdr = (nvlink_inband_msg_header_t*)buffer;
3586 
3587     if (nvswitch_is_message_persistent(device, msghdr))
3588     {
3589          if (nvListCount(&device->link[linkId].inbandData.persistent_list) <
3590              device->hal.nvswitch_get_max_persistent_message_count(device))
3591          {
3592          nvListAdd(&msg->entry, &device->link[linkId].inbandData.persistent_list);
3593     }
3594     else
3595     {
3596              bSendNackOrDrop = NV_TRUE;
3597          }
3598     }
3599     else
3600     {
3601          if (driver_fabric_state == NVSWITCH_DRIVER_FABRIC_STATE_CONFIGURED)
3602          {
3603               nvListAdd(&msg->entry,
3604                         &device->link[linkId].inbandData.nonpersistent_list);
3605          }
3606          else
3607          {
3608               bSendNackOrDrop = NV_TRUE;
3609          }
3610     }
3611 
3612     if (bSendNackOrDrop)
3613     {
3614         nvswitch_send_nack_or_drop(device, linkId, msghdr);
3615         nvswitch_os_free(msg);
3616     }
3617     else
3618     {
3619     status = nvswitch_lib_notify_client_events(device,
3620                                                NVSWITCH_DEVICE_EVENT_INBAND_DATA);
3621     if (status != NVL_SUCCESS)
3622     {
3623           NVSWITCH_PRINT(device, ERROR, "%s: Failed to notify INBAND_DATA event\n",
3624                          __FUNCTION__);
3625     }
3626     }
3627 
3628     device->link[linkId].inbandData.message = NULL;
3629 }
3630 
3631 /*
3632  * @Brief : Constructs an NVS link struct with the given data
3633  *
3634  * @Description :
3635  *
3636  * @param[in] device            NvSwitch device to contain this link
3637  * @param[in] link_num          link number of the link
3638  * @param[out] link             reference to store the created link into
3639  *
3640  * @returns                     NVL_SUCCESS if action succeeded,
3641  *                              -NVL_NO_MEM if memory allocation failed
3642  */
3643 NvlStatus
3644 nvswitch_create_link
3645 (
3646     nvswitch_device *device,
3647     NvU32 link_number,
3648     nvlink_link **link
3649 )
3650 {
3651     NvlStatus   retval      = NVL_SUCCESS;
3652     nvlink_link *ret        = NULL;
3653     LINK_INFO   *link_info  = NULL;
3654     NvU64       ac_coupled_mask;
3655 
3656     NVSWITCH_ASSERT(nvswitch_get_num_links(device) <=  NVSWITCH_MAX_NUM_LINKS);
3657 
3658     ret = nvswitch_os_malloc(sizeof(*ret));
3659     if (NULL == ret)
3660     {
3661         NVSWITCH_PRINT(device, ERROR,
3662             "nvswitch_os_malloc during link creation failed!\n");
3663         retval = -NVL_NO_MEM;
3664         goto nvswitch_create_link_cleanup;
3665     }
3666     nvswitch_os_memset(ret, 0, sizeof(*ret));
3667 
3668     link_info = nvswitch_os_malloc(sizeof(*link_info));
3669     if (NULL == link_info)
3670     {
3671         NVSWITCH_PRINT(device, ERROR,
3672             "nvswitch_os_malloc during link creation failed!\n");
3673         retval = -NVL_NO_MEM;
3674         goto nvswitch_create_link_cleanup;
3675     }
3676     nvswitch_os_memset(link_info, 0, sizeof(*link_info));
3677     nvswitch_os_snprintf(link_info->name, sizeof(link_info->name), NVSWITCH_LINK_NAME "%d", link_number);
3678 
3679     ret->dev        = device->nvlink_device;
3680     ret->linkName   = link_info->name;
3681     ret->linkNumber = link_number;
3682     ret->state      = NVLINK_LINKSTATE_OFF;
3683     ret->ac_coupled = NV_FALSE;
3684     ret->version    = nvswitch_get_link_ip_version(device, link_number);
3685 
3686     ac_coupled_mask = ((NvU64)device->regkeys.ac_coupled_mask2 << 32 |
3687                        (NvU64)device->regkeys.ac_coupled_mask);
3688 
3689     if (ac_coupled_mask)
3690     {
3691         if (ac_coupled_mask & NVBIT64(link_number))
3692         {
3693             ret->ac_coupled = NV_TRUE;
3694         }
3695     }
3696     else if (device->firmware.nvlink.link_config_found)
3697     {
3698         if (device->firmware.nvlink.link_ac_coupled_mask & NVBIT64(link_number))
3699         {
3700             ret->ac_coupled = NV_TRUE;
3701         }
3702     }
3703 
3704     // Initialize NVLink corelib callbacks for switch
3705     nvswitch_get_link_handlers(&link_handlers);
3706 
3707     ret->link_handlers = &link_handlers;
3708 
3709     //
3710     // link_info is used to store private link information
3711     //
3712 
3713     ret->link_info = link_info;
3714 
3715     *link = ret;
3716 
3717     return retval;
3718 
3719 nvswitch_create_link_cleanup:
3720     if (NULL != ret)
3721     {
3722         nvswitch_os_free(ret);
3723     }
3724     if (NULL != link_info)
3725     {
3726         nvswitch_os_free(link_info);
3727     }
3728 
3729     return retval;
3730 }
3731 
3732 void
3733 nvswitch_destroy_link
3734 (
3735     nvlink_link *link
3736 )
3737 {
3738     if (NULL != link->link_info)
3739     {
3740         nvswitch_os_free(link->link_info);
3741     }
3742 
3743     nvswitch_os_free(link);
3744 }
3745 
3746 NvU32
3747 nvswitch_get_num_links
3748 (
3749     nvswitch_device *device
3750 )
3751 {
3752     return device->hal.nvswitch_get_num_links(device);
3753 }
3754 
3755 NvBool
3756 nvswitch_is_link_valid
3757 (
3758     nvswitch_device *device,
3759     NvU32            link_id
3760 )
3761 {
3762     return device->hal.nvswitch_is_link_valid(device, link_id);
3763 }
3764 
3765 nvlink_link*
3766 nvswitch_get_link(nvswitch_device *device, NvU8 link_id)
3767 {
3768     nvlink_link *link = NULL;
3769 
3770     nvlink_lib_get_link(device->nvlink_device, link_id, &link);
3771 
3772     return link;
3773 }
3774 
3775 NvU64
3776 nvswitch_get_enabled_link_mask
3777 (
3778     nvswitch_device *device
3779 )
3780 {
3781     NvU64                    ret;
3782     nvlink_link             *link;
3783     NvU32 link_num;
3784 
3785     ret = 0x0;
3786 
3787     for (link_num = 0; link_num < nvswitch_get_num_links(device); link_num++)
3788     {
3789         if (nvlink_lib_get_link(device->nvlink_device, link_num, &link) == NVL_SUCCESS)
3790         {
3791             ret |= NVBIT64(link_num);
3792         }
3793     }
3794 
3795     return ret;
3796 }
3797 
3798 void
3799 nvswitch_set_fatal_error
3800 (
3801     nvswitch_device *device,
3802     NvBool           device_fatal,
3803     NvU32            link_id
3804 )
3805 {
3806     device->hal.nvswitch_set_fatal_error(device, device_fatal, link_id);
3807 }
3808 
3809 NvU32
3810 nvswitch_get_swap_clk_default
3811 (
3812     nvswitch_device *device
3813 )
3814 {
3815     return device->hal.nvswitch_get_swap_clk_default(device);
3816 }
3817 
3818 NvU32
3819 nvswitch_get_latency_sample_interval_msec
3820 (
3821     nvswitch_device *device
3822 )
3823 {
3824     return device->hal.nvswitch_get_latency_sample_interval_msec(device);
3825 }
3826 
3827 void
3828 nvswitch_internal_latency_bin_log
3829 (
3830     nvswitch_device *device
3831 )
3832 {
3833     device->hal.nvswitch_internal_latency_bin_log(device);
3834 }
3835 
3836 void
3837 nvswitch_ecc_writeback_task
3838 (
3839     nvswitch_device *device
3840 )
3841 {
3842     device->hal.nvswitch_ecc_writeback_task(device);
3843 }
3844 
3845 void
3846 nvswitch_monitor_thermal_alert
3847 (
3848     nvswitch_device *device
3849 )
3850 {
3851     device->hal.nvswitch_monitor_thermal_alert(device);
3852 }
3853 
3854 void
3855 nvswitch_hw_counter_shutdown
3856 (
3857     nvswitch_device *device
3858 )
3859 {
3860     device->hal.nvswitch_hw_counter_shutdown(device);
3861 }
3862 
3863 NvlStatus
3864 nvswitch_get_rom_info
3865 (
3866     nvswitch_device *device,
3867     NVSWITCH_EEPROM_TYPE *eeprom
3868 )
3869 {
3870     return device->hal.nvswitch_get_rom_info(device, eeprom);
3871 }
3872 
3873 void
3874 nvswitch_lib_enable_interrupts
3875 (
3876     nvswitch_device *device
3877 )
3878 {
3879     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
3880     {
3881         NVSWITCH_ASSERT(0);
3882         return;
3883     }
3884 
3885     device->hal.nvswitch_lib_enable_interrupts(device);
3886 }
3887 
3888 void
3889 nvswitch_lib_disable_interrupts
3890 (
3891     nvswitch_device *device
3892 )
3893 {
3894     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
3895     {
3896         NVSWITCH_ASSERT(0);
3897         return;
3898     }
3899 
3900     device->hal.nvswitch_lib_disable_interrupts(device);
3901 }
3902 
3903 NvlStatus
3904 nvswitch_lib_check_interrupts
3905 (
3906     nvswitch_device *device
3907 )
3908 {
3909     if (!NVSWITCH_IS_DEVICE_INITIALIZED(device))
3910     {
3911         return -NVL_BAD_ARGS;
3912     }
3913 
3914     return device->hal.nvswitch_lib_check_interrupts(device);
3915 }
3916 
3917 NvlStatus
3918 nvswitch_lib_service_interrupts
3919 (
3920     nvswitch_device *device
3921 )
3922 {
3923     if (!NVSWITCH_IS_DEVICE_INITIALIZED(device))
3924     {
3925         return -NVL_BAD_ARGS;
3926     }
3927 
3928     return device->hal.nvswitch_lib_service_interrupts(device);
3929 }
3930 
3931 NvU64
3932 nvswitch_hw_counter_read_counter
3933 (
3934     nvswitch_device *device
3935 )
3936 {
3937     return device->hal.nvswitch_hw_counter_read_counter(device);
3938 }
3939 
3940 NvU32
3941 nvswitch_get_link_ip_version
3942 (
3943     nvswitch_device *device,
3944     NvU32            link_id
3945 )
3946 {
3947     return device->hal.nvswitch_get_link_ip_version(device, link_id);
3948 }
3949 
3950 NvU32
3951 nvswitch_reg_read_32
3952 (
3953     nvswitch_device *device,
3954     NvU32 offset
3955 )
3956 {
3957     NvU32 val;
3958 
3959     if (device->nvlink_device->pciInfo.bars[0].pBar == NULL)
3960     {
3961         NVSWITCH_PRINT(device, ERROR,
3962             "register read failed at offset 0x%x\n", offset);
3963 
3964         return 0xFFFFFFFF;
3965     }
3966 
3967     val = nvswitch_os_mem_read32((NvU8 *)device->nvlink_device->pciInfo.bars[0].pBar + offset);
3968 
3969     if ((val & 0xFFFF0000) == 0xBADF0000)
3970     {
3971         NvU32 boot_0;
3972         NVSWITCH_PRINT(device, WARN,
3973             "Potential IO failure reading 0x%x (0x%x)\n", offset, val);
3974         boot_0 = nvswitch_os_mem_read32((NvU8 *)device->nvlink_device->pciInfo.bars[0].pBar + 0x0);
3975 
3976         if ((boot_0 & 0xFFFF0000) == 0xBADF0000)
3977         {
3978             NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_IO_FAILURE,
3979                 "IO failure\n");
3980             NVSWITCH_PRINT(device, ERROR,
3981                 "IO failure reading 0x%x (0x%x)\n", offset, val);
3982         }
3983     }
3984 
3985 #ifdef _VERBOSE_REG_ACCESS
3986     NVSWITCH_PRINT(device, SETUP,
3987         "NVSWITCH read 0x%6x+%6x = 0x%08x\n",
3988         device->nvlink_device->pciInfo.bars[0].baseAddr, offset, val);
3989 #endif
3990 
3991     return val;
3992 }
3993 
3994 void
3995 nvswitch_reg_write_32
3996 (
3997     nvswitch_device *device,
3998     NvU32 offset,
3999     NvU32 data
4000 )
4001 {
4002     if (device->nvlink_device->pciInfo.bars[0].pBar == NULL)
4003     {
4004         NVSWITCH_PRINT(device, ERROR,
4005             "register write failed at offset 0x%x\n", offset);
4006 
4007         return;
4008     }
4009 
4010 #ifdef _VERBOSE_REG_ACCESS
4011     NVSWITCH_PRINT(device, SETUP,
4012         "NVSWITCH write 0x%6x+%6x = 0x%08x\n",
4013         device->nvlink_device->pciInfo.bars[0].baseAddr, offset, data);
4014 #endif
4015 
4016     // Write the register
4017     nvswitch_os_mem_write32((NvU8 *)device->nvlink_device->pciInfo.bars[0].pBar + offset, data);
4018 
4019     return;
4020 }
4021 
4022 NvU64
4023 nvswitch_read_64bit_counter
4024 (
4025     nvswitch_device *device,
4026     NvU32 lo_offset,
4027     NvU32 hi_offset
4028 )
4029 {
4030     NvU32   hi0;
4031     NvU32   hi1;
4032     NvU32   lo;
4033 
4034     hi0 = nvswitch_reg_read_32(device, hi_offset);
4035     do
4036     {
4037         hi1 = hi0;
4038         lo  = nvswitch_reg_read_32(device, lo_offset);
4039         hi0 = nvswitch_reg_read_32(device, hi_offset);
4040     } while (hi0 != hi1);
4041 
4042     return (lo | ((NvU64)hi0 << 32));
4043 }
4044 
4045 NvlStatus
4046 nvswitch_validate_pll_config
4047 (
4048     nvswitch_device *device,
4049     NVSWITCH_PLL_INFO *switch_pll,
4050     NVSWITCH_PLL_LIMITS default_pll_limits
4051 )
4052 {
4053     NvU32 update_rate_khz;
4054     NvU32 vco_freq_khz;
4055     NVSWITCH_PLL_LIMITS pll_limits;
4056 
4057     NVSWITCH_PRINT(device, SETUP,
4058         "%s: Validating PLL: %dkHz * %d / (%d * %d * (1 << %d))\n",
4059         __FUNCTION__,
4060         switch_pll->src_freq_khz,
4061         switch_pll->N,
4062         switch_pll->M,
4063         switch_pll->PL,
4064         switch_pll->dist_mode);
4065 
4066     //
4067     // These parameters could come from schmoo'ing API, settings file or a ROM.
4068     // For now, hard code with POR.
4069     //
4070     if (device->firmware.firmware_size > 0 &&
4071         device->firmware.clocks.clocks_found &&
4072         device->firmware.clocks.sys_pll.valid)
4073     {
4074         pll_limits = device->firmware.clocks.sys_pll;
4075     }
4076     else
4077     {
4078         pll_limits = default_pll_limits;
4079     }
4080 
4081     NVSWITCH_ASSERT(switch_pll->M != 0);
4082     NVSWITCH_ASSERT(switch_pll->PL != 0);
4083 
4084     if ((switch_pll->src_freq_khz < pll_limits.ref_min_mhz * 1000) ||
4085         (switch_pll->src_freq_khz > pll_limits.ref_max_mhz * 1000))
4086     {
4087         NVSWITCH_PRINT(device, ERROR,
4088             "%s: ERROR: Ref(%d) out-of-range\n",
4089             __FUNCTION__,
4090             switch_pll->src_freq_khz);
4091         return -NVL_ERR_INVALID_STATE;
4092     }
4093 
4094     if ((switch_pll->M < pll_limits.m_min) ||
4095         (switch_pll->M > pll_limits.m_max))
4096     {
4097         NVSWITCH_PRINT(device, ERROR,
4098             "%s: ERROR: M(%d) out-of-range\n",
4099             __FUNCTION__,
4100             switch_pll->M);
4101         return -NVL_ERR_INVALID_STATE;
4102     }
4103 
4104     if ((switch_pll->N < pll_limits.n_min) ||
4105         (switch_pll->N > pll_limits.n_max))
4106     {
4107         NVSWITCH_PRINT(device, ERROR,
4108             "%s: ERROR: N(%d) out-of-range\n",
4109             __FUNCTION__,
4110             switch_pll->N);
4111         return -NVL_ERR_INVALID_STATE;
4112     }
4113 
4114     if ((switch_pll->PL < pll_limits.pl_min) ||
4115         (switch_pll->PL > pll_limits.pl_max))
4116     {
4117         NVSWITCH_PRINT(device, ERROR,
4118             "%s: ERROR: PL(%d) out-of-range\n",
4119             __FUNCTION__,
4120             switch_pll->PL);
4121         return -NVL_ERR_INVALID_STATE;
4122     }
4123 
4124     vco_freq_khz = switch_pll->src_freq_khz * switch_pll->N
4125         / switch_pll->M;
4126     if ((vco_freq_khz < pll_limits.vco_min_mhz * 1000) ||
4127         (vco_freq_khz > pll_limits.vco_max_mhz * 1000))
4128     {
4129         NVSWITCH_PRINT(device, ERROR,
4130             "%s: ERROR: VCO(%d) freq out-of-range\n",
4131             __FUNCTION__,
4132             vco_freq_khz);
4133         return -NVL_ERR_INVALID_STATE;
4134     }
4135 
4136     update_rate_khz = switch_pll->src_freq_khz / switch_pll->M;
4137     if ((update_rate_khz < pll_limits.update_min_mhz * 1000) ||
4138         (update_rate_khz > pll_limits.update_max_mhz * 1000))
4139     {
4140         NVSWITCH_PRINT(device, ERROR,
4141             "%s: ERROR: update rate(%d) out-of-range\n",
4142             __FUNCTION__,
4143             update_rate_khz);
4144         return -NVL_ERR_INVALID_STATE;
4145     }
4146 
4147     switch_pll->vco_freq_khz = vco_freq_khz;
4148 
4149     switch_pll->freq_khz =
4150         switch_pll->src_freq_khz * switch_pll->N /
4151         (switch_pll->M * switch_pll->PL * (1 << switch_pll->dist_mode));
4152 
4153     NVSWITCH_PRINT(device, SETUP,
4154         "%s: Validated PLL: %dkHz * %d / (%d * %d * (1 << %d)) = %dkHz\n",
4155         __FUNCTION__,
4156         switch_pll->src_freq_khz,
4157         switch_pll->N,
4158         switch_pll->M,
4159         switch_pll->PL,
4160         switch_pll->dist_mode,
4161         switch_pll->freq_khz);
4162 
4163     return NVL_SUCCESS;
4164 }
4165 
4166 NvlStatus
4167 nvswitch_init_pll_config
4168 (
4169     nvswitch_device *device
4170 )
4171 {
4172     return device->hal.nvswitch_init_pll_config(device);
4173 }
4174 
4175 NvlStatus
4176 nvswitch_init_pll
4177 (
4178     nvswitch_device *device
4179 )
4180 {
4181     return device->hal.nvswitch_init_pll(device);
4182 }
4183 
4184 void
4185 nvswitch_init_clock_gating
4186 (
4187     nvswitch_device *device
4188 )
4189 {
4190     return device->hal.nvswitch_init_clock_gating(device);
4191 }
4192 
4193 void
4194 nvswitch_lib_get_uuid
4195 (
4196     nvswitch_device *device,
4197     NvUuid *uuid
4198 )
4199 {
4200     if (!NVSWITCH_IS_DEVICE_INITIALIZED(device) || (uuid == NULL))
4201     {
4202         return;
4203     }
4204 
4205     nvswitch_os_memcpy(uuid, &device->uuid, sizeof(device->uuid));
4206 }
4207 
4208 NvlStatus
4209 nvswitch_lib_get_physid
4210 (
4211     nvswitch_device *device,
4212     NvU32 *phys_id
4213 )
4214 {
4215     NVSWITCH_GET_INFO get_info;
4216     NvlStatus ret;
4217 
4218     if (phys_id == NULL || !NVSWITCH_IS_DEVICE_ACCESSIBLE(device))
4219     {
4220         return -NVL_BAD_ARGS;
4221     }
4222 
4223     get_info.count=1;
4224     get_info.index[0] = NVSWITCH_GET_INFO_INDEX_PHYSICAL_ID;
4225 
4226     ret = _nvswitch_ctrl_get_info(device, &get_info);
4227     if (ret != NVL_SUCCESS)
4228     {
4229         NVSWITCH_PRINT(device, ERROR,
4230             "Failed to get physical ID\n");
4231         return ret;
4232     }
4233 
4234     *phys_id = get_info.info[0];
4235 
4236     return NVL_SUCCESS;
4237 }
4238 
4239 void
4240 nvswitch_i2c_set_hw_speed_mode
4241 (
4242     nvswitch_device *device,
4243     NvU32 port,
4244     NvU32 speedMode
4245 )
4246 {
4247     device->hal.nvswitch_i2c_set_hw_speed_mode(device, port, speedMode);
4248     return;
4249 }
4250 
4251 void
4252 nvswitch_lib_smbpbi_log_sxid
4253 (
4254     nvswitch_device *device,
4255     NvU32           sxid,
4256     const char      *pFormat,
4257     ...
4258 )
4259 {
4260     va_list arglist;
4261     int     msglen;
4262     char    string[RM_SOE_SMBPBI_CMD_LOG_MESSAGE_MAX_STRING + 1];
4263 
4264     nvswitch_os_memset(string, 0, (NvLength)sizeof(string));
4265 
4266     va_start(arglist, pFormat);
4267     msglen = nvswitch_os_vsnprintf(string, sizeof(string), pFormat, arglist);
4268     va_end(arglist);
4269 
4270     if (!(msglen < 0))
4271     {
4272         //
4273         // HALs will know that the string is being truncated by seeing that the
4274         // last byte in the buffer is not nul.
4275         //
4276         msglen = NV_MIN(msglen + 1, (int)RM_SOE_SMBPBI_CMD_LOG_MESSAGE_MAX_STRING);
4277         device->hal.nvswitch_smbpbi_log_message(device, sxid, msglen, (NvU8 *) string);
4278     }
4279 }
4280 
4281 NvlStatus
4282 nvswitch_set_minion_initialized
4283 (
4284     nvswitch_device *device,
4285     NvU32 idx_minion,
4286     NvBool initialized
4287 )
4288 {
4289     return device->hal.nvswitch_set_minion_initialized(device, idx_minion, initialized);
4290 }
4291 
4292 NvBool
4293 nvswitch_is_minion_initialized
4294 (
4295     nvswitch_device *device,
4296     NvU32 idx_minion
4297 )
4298 {
4299     return device->hal.nvswitch_is_minion_initialized(device, idx_minion);
4300 }
4301 
4302 NvlStatus
4303 nvswitch_device_discovery
4304 (
4305     nvswitch_device *device,
4306     NvU32 discovery_offset
4307 )
4308 {
4309     return device->hal.nvswitch_device_discovery(device, discovery_offset);
4310 }
4311 
4312 void
4313 nvswitch_filter_discovery
4314 (
4315     nvswitch_device *device
4316 )
4317 {
4318     device->hal.nvswitch_filter_discovery(device);
4319 }
4320 
4321 NvlStatus
4322 nvswitch_process_discovery
4323 (
4324     nvswitch_device *device
4325 )
4326 {
4327     return device->hal.nvswitch_process_discovery(device);
4328 }
4329 
4330 NvlStatus
4331 nvswitch_init_minion
4332 (
4333     nvswitch_device *device
4334 )
4335 {
4336     return device->hal.nvswitch_init_minion(device);
4337 }
4338 
4339 NvU32
4340 nvswitch_get_link_eng_inst
4341 (
4342     nvswitch_device *device,
4343     NvU32 link_id,
4344     NVSWITCH_ENGINE_ID eng_id
4345 )
4346 {
4347     return device->hal.nvswitch_get_link_eng_inst(device, link_id, eng_id);
4348 }
4349 
4350 void *
4351 nvswitch_alloc_chipdevice
4352 (
4353     nvswitch_device *device
4354 )
4355 {
4356     return(device->hal.nvswitch_alloc_chipdevice(device));
4357 }
4358 
4359 void
4360 nvswitch_free_chipdevice
4361 (
4362     nvswitch_device *device
4363 )
4364 {
4365     if (device->chip_device)
4366     {
4367         nvswitch_os_free(device->chip_device);
4368         device->chip_device = NULL;
4369     }
4370 }
4371 
4372 NvlStatus
4373 nvswitch_init_thermal
4374 (
4375     nvswitch_device *device
4376 )
4377 {
4378     return(device->hal.nvswitch_init_thermal(device));
4379 }
4380 
4381 NvU32
4382 nvswitch_read_physical_id
4383 (
4384     nvswitch_device *device
4385 )
4386 {
4387     return(device->hal.nvswitch_read_physical_id(device));
4388 }
4389 
4390 NvU32
4391 nvswitch_get_caps_nvlink_version
4392 (
4393     nvswitch_device *device
4394 )
4395 {
4396     return(device->hal.nvswitch_get_caps_nvlink_version(device));
4397 }
4398 
4399 void
4400 nvswitch_initialize_interrupt_tree
4401 (
4402     nvswitch_device *device
4403 )
4404 {
4405     device->hal.nvswitch_initialize_interrupt_tree(device);
4406 }
4407 
4408 void
4409 nvswitch_init_dlpl_interrupts
4410 (
4411     nvlink_link *link
4412 )
4413 {
4414     nvswitch_device *device = link->dev->pDevInfo;
4415 
4416     device->hal.nvswitch_init_dlpl_interrupts(link);
4417 }
4418 
4419 NvlStatus
4420 nvswitch_initialize_pmgr
4421 (
4422     nvswitch_device *device
4423 )
4424 {
4425     return(device->hal.nvswitch_initialize_pmgr(device));
4426 }
4427 
4428 NvlStatus
4429 nvswitch_initialize_ip_wrappers
4430 (
4431     nvswitch_device *device
4432 )
4433 {
4434     return(device->hal.nvswitch_initialize_ip_wrappers(device));
4435 }
4436 
4437 NvlStatus
4438 nvswitch_initialize_route
4439 (
4440     nvswitch_device *device
4441 )
4442 {
4443     return(device->hal.nvswitch_initialize_route(device));
4444 }
4445 
4446 void
4447 nvswitch_soe_unregister_events
4448 (
4449     nvswitch_device *device
4450 )
4451 {
4452     device->hal.nvswitch_soe_unregister_events(device);
4453 }
4454 
4455 NvlStatus
4456 nvswitch_soe_register_event_callbacks
4457 (
4458     nvswitch_device *device
4459 )
4460 {
4461     return device->hal.nvswitch_soe_register_event_callbacks(device);
4462 }
4463 
4464 NVSWITCH_BIOS_NVLINK_CONFIG *
4465 nvswitch_get_bios_nvlink_config
4466 (
4467     nvswitch_device *device
4468 )
4469 {
4470     return(device->hal.nvswitch_get_bios_nvlink_config(device));
4471 }
4472 
4473 NvlStatus
4474 nvswitch_minion_send_command
4475 (
4476     nvswitch_device *device,
4477     NvU32            linkNumber,
4478     NvU32            command,
4479     NvU32            scratch0
4480 )
4481 {
4482     return(device->hal.nvswitch_minion_send_command(device, linkNumber,
4483                                                     command, scratch0));
4484 }
4485 
4486 NvlStatus
4487 nvswitch_init_nport
4488 (
4489     nvswitch_device *device
4490 )
4491 {
4492     return device->hal.nvswitch_init_nport(device);
4493 }
4494 
4495 NvlStatus
4496 nvswitch_init_nxbar
4497 (
4498     nvswitch_device *device
4499 )
4500 {
4501     return device->hal.nvswitch_init_nxbar(device);
4502 }
4503 
4504 NvlStatus
4505 nvswitch_clear_nport_rams
4506 (
4507     nvswitch_device *device
4508 )
4509 {
4510     return device->hal.nvswitch_clear_nport_rams(device);
4511 }
4512 
4513 NvlStatus
4514 nvswitch_pri_ring_init
4515 (
4516     nvswitch_device *device
4517 )
4518 {
4519     return(device->hal.nvswitch_pri_ring_init(device));
4520 }
4521 
4522 NvlStatus
4523 nvswitch_get_remap_table_selector
4524 (
4525     nvswitch_device *device,
4526     NVSWITCH_TABLE_SELECT_REMAP table_selector,
4527     NvU32 *remap_ram_sel
4528 )
4529 {
4530     return device->hal.nvswitch_get_remap_table_selector(device, table_selector, remap_ram_sel);
4531 }
4532 
4533 NvU32
4534 nvswitch_get_ingress_ram_size
4535 (
4536     nvswitch_device *device,
4537     NvU32 ingress_ram_selector      // NV_INGRESS_REQRSPMAPADDR_RAM_ADDRESS_*
4538 )
4539 {
4540     return device->hal.nvswitch_get_ingress_ram_size(device, ingress_ram_selector);
4541 }
4542 
4543 NvlStatus
4544 nvswitch_minion_get_dl_status
4545 (
4546     nvswitch_device *device,
4547     NvU32            linkId,
4548     NvU32            statusIdx,
4549     NvU32            statusArgs,
4550     NvU32           *statusData
4551 )
4552 {
4553     return device->hal.nvswitch_minion_get_dl_status(device, linkId, statusIdx, statusArgs, statusData);
4554 }
4555 
4556 NvBool
4557 nvswitch_is_i2c_supported
4558 (
4559     nvswitch_device *device
4560 )
4561 {
4562     return device->hal.nvswitch_is_i2c_supported(device);
4563 }
4564 
4565 
4566 NvlStatus
4567 nvswitch_poll_sublink_state
4568 (
4569     nvswitch_device *device,
4570     nvlink_link *link
4571 )
4572 {
4573     return device->hal.nvswitch_poll_sublink_state(device, link);
4574 }
4575 
4576 void
4577 nvswitch_setup_link_loopback_mode
4578 (
4579     nvswitch_device *device,
4580     NvU32            linkNumber
4581 )
4582 {
4583     return device->hal.nvswitch_setup_link_loopback_mode(device, linkNumber);
4584 }
4585 
4586 void
4587 nvswitch_reset_persistent_link_hw_state
4588 (
4589     nvswitch_device *device,
4590     NvU32            linkNumber
4591 )
4592 {
4593     return device->hal.nvswitch_reset_persistent_link_hw_state(device, linkNumber);
4594 }
4595 
4596 void
4597 nvswitch_store_topology_information
4598 (
4599     nvswitch_device *device,
4600     nvlink_link *link
4601 )
4602 {
4603     return device->hal.nvswitch_store_topology_information(device, link);
4604 }
4605 
4606 void
4607 nvswitch_init_lpwr_regs
4608 (
4609     nvlink_link *link
4610 )
4611 {
4612    nvswitch_device *device = link->dev->pDevInfo;
4613    device->hal.nvswitch_init_lpwr_regs(link);
4614 }
4615 
4616 NvlStatus
4617 nvswitch_launch_ALI
4618 (
4619     nvswitch_device *device
4620 )
4621 {
4622     return device->hal.nvswitch_launch_ALI(device);
4623 }
4624 
4625 NvlStatus
4626 nvswitch_set_training_mode
4627 (
4628     nvswitch_device *device
4629 )
4630 {
4631     return device->hal.nvswitch_set_training_mode(device);
4632 }
4633 
4634 NvBool
4635 nvswitch_is_link_in_reset
4636 (
4637     nvswitch_device *device,
4638     nvlink_link     *link
4639 )
4640 {
4641     return device->hal.nvswitch_is_link_in_reset(device, link);
4642 }
4643 
4644 NvBool
4645 nvswitch_i2c_is_device_access_allowed
4646 (
4647     nvswitch_device *device,
4648     NvU32 port,
4649     NvU8 addr,
4650     NvBool bIsRead
4651 )
4652 {
4653     return device->hal.nvswitch_i2c_is_device_access_allowed(device, port, addr, bIsRead);
4654 }
4655 
4656 NvlStatus
4657 nvswitch_parse_bios_image
4658 (
4659     nvswitch_device *device
4660 )
4661 {
4662     return device->hal.nvswitch_parse_bios_image(device);
4663 }
4664 
4665 void
4666 nvswitch_init_buffer_ready
4667 (
4668     nvswitch_device *device,
4669     nvlink_link *link,
4670     NvBool bNportBufferReady
4671 )
4672 {
4673     return device->hal.nvswitch_init_buffer_ready(device, link, bNportBufferReady);
4674 }
4675 
4676 void
4677 nvswitch_apply_recal_settings
4678 (
4679     nvswitch_device *device,
4680     nvlink_link *link
4681 )
4682 {
4683     return device->hal.nvswitch_apply_recal_settings(device, link);
4684 }
4685 
4686 NvlStatus
4687 nvswitch_launch_ALI_link_training
4688 (
4689     nvswitch_device *device,
4690     nvlink_link *link,
4691     NvBool bSync
4692 )
4693 {
4694     return device->hal.nvswitch_launch_ALI_link_training(device, link, bSync);
4695 }
4696 
4697 NvlStatus
4698 nvswitch_reset_and_train_link
4699 (
4700     nvswitch_device *device,
4701     nvlink_link     *link
4702 )
4703 {
4704     return device->hal.nvswitch_reset_and_train_link(device, link);
4705 }
4706 
4707 static NvlStatus
4708 _nvswitch_ctrl_get_err_info
4709 (
4710     nvswitch_device *device,
4711     NVSWITCH_NVLINK_GET_ERR_INFO_PARAMS *ret
4712 )
4713 {
4714     return device->hal.nvswitch_ctrl_get_err_info(device, ret);
4715 }
4716 
4717 static NvlStatus
4718 _nvswitch_ctrl_clear_counters
4719 (
4720     nvswitch_device *device,
4721     NVSWITCH_NVLINK_CLEAR_COUNTERS_PARAMS *ret
4722 )
4723 {
4724     return device->hal.nvswitch_ctrl_clear_counters(device, ret);
4725 }
4726 
4727 void
4728 nvswitch_setup_link_system_registers
4729 (
4730     nvswitch_device *device,
4731     nvlink_link *link
4732 )
4733 {
4734     device->hal.nvswitch_setup_link_system_registers(device, link);
4735 }
4736 
4737 void
4738 nvswitch_load_link_disable_settings
4739 (
4740     nvswitch_device *device,
4741     nvlink_link *link
4742 )
4743 {
4744     device->hal.nvswitch_load_link_disable_settings(device, link);
4745 }
4746 
4747 static NvlStatus
4748 _nvswitch_ctrl_set_nvlink_error_threshold
4749 (
4750     nvswitch_device *device,
4751     NVSWITCH_SET_NVLINK_ERROR_THRESHOLD_PARAMS *pParams
4752 )
4753 {
4754     return device->hal.nvswitch_ctrl_set_nvlink_error_threshold(device, pParams);
4755 }
4756 
4757 static NvlStatus
4758 _nvswitch_ctrl_get_nvlink_error_threshold
4759 (
4760     nvswitch_device *device,
4761     NVSWITCH_GET_NVLINK_ERROR_THRESHOLD_PARAMS *pParams
4762 )
4763 {
4764     return device->hal.nvswitch_ctrl_get_nvlink_error_threshold(device, pParams);
4765 }
4766 
4767 static NvlStatus
4768 _nvswitch_ctrl_therm_read_voltage
4769 (
4770     nvswitch_device *device,
4771     NVSWITCH_CTRL_GET_VOLTAGE_PARAMS *info
4772 )
4773 {
4774     return device->hal.nvswitch_ctrl_therm_read_voltage(device, info);
4775 }
4776 
4777 static NvlStatus
4778 _nvswitch_ctrl_therm_read_power
4779 (
4780     nvswitch_device *device,
4781     NVSWITCH_GET_POWER_PARAMS *info
4782 )
4783 {
4784     return device->hal.nvswitch_ctrl_therm_read_power(device, info);
4785 }
4786 
4787 NvlStatus
4788 nvswitch_lib_ctrl
4789 (
4790     nvswitch_device *device,
4791     NvU32 cmd,
4792     void *params,
4793     NvU64 size,
4794     void *osPrivate
4795 )
4796 {
4797     NvlStatus retval;
4798     NvU64 flags = 0;
4799 
4800     if (!NVSWITCH_IS_DEVICE_ACCESSIBLE(device) || params == NULL)
4801     {
4802         return -NVL_BAD_ARGS;
4803     }
4804 
4805     flags = NVSWITCH_DEV_CMD_CHECK_ADMIN | NVSWITCH_DEV_CMD_CHECK_FM;
4806     switch (cmd)
4807     {
4808         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_INFO,
4809                 _nvswitch_ctrl_get_info,
4810                 NVSWITCH_GET_INFO);
4811         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_INTERNAL_LATENCY,
4812                 _nvswitch_ctrl_get_internal_latency,
4813                 NVSWITCH_GET_INTERNAL_LATENCY);
4814         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_NVLIPT_COUNTERS,
4815                 _nvswitch_ctrl_get_nvlipt_counters,
4816                 NVSWITCH_GET_NVLIPT_COUNTERS);
4817         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_ERRORS,
4818                 nvswitch_ctrl_get_errors,
4819                 NVSWITCH_GET_ERRORS_PARAMS);
4820         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_NVLINK_STATUS,
4821                 _nvswitch_ctrl_get_nvlink_status,
4822                 NVSWITCH_GET_NVLINK_STATUS_PARAMS);
4823         NVSWITCH_DEV_CMD_DISPATCH_WITH_PRIVATE_DATA(
4824                 CTRL_NVSWITCH_ACQUIRE_CAPABILITY,
4825                 _nvswitch_ctrl_acquire_capability,
4826                 NVSWITCH_ACQUIRE_CAPABILITY_PARAMS,
4827                 osPrivate);
4828         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_TEMPERATURE,
4829                 _nvswitch_ctrl_therm_read_temperature,
4830                 NVSWITCH_CTRL_GET_TEMPERATURE_PARAMS);
4831         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_THROUGHPUT_COUNTERS,
4832                 nvswitch_ctrl_get_throughput_counters,
4833                 NVSWITCH_GET_THROUGHPUT_COUNTERS_PARAMS);
4834         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_FATAL_ERROR_SCOPE,
4835                 _nvswitch_ctrl_get_fatal_error_scope,
4836                 NVSWITCH_GET_FATAL_ERROR_SCOPE_PARAMS);
4837         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4838                 CTRL_NVSWITCH_SET_SWITCH_PORT_CONFIG,
4839                 _nvswitch_ctrl_set_switch_port_config,
4840                 NVSWITCH_SET_SWITCH_PORT_CONFIG,
4841                 osPrivate, flags);
4842         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4843                 CTRL_NVSWITCH_GET_INGRESS_REQUEST_TABLE,
4844                 _nvswitch_ctrl_get_ingress_request_table,
4845                 NVSWITCH_GET_INGRESS_REQUEST_TABLE_PARAMS,
4846                 osPrivate, flags);
4847         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4848                 CTRL_NVSWITCH_SET_INGRESS_REQUEST_TABLE,
4849                 _nvswitch_ctrl_set_ingress_request_table,
4850                 NVSWITCH_SET_INGRESS_REQUEST_TABLE,
4851                 osPrivate, flags);
4852         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4853                 CTRL_NVSWITCH_SET_INGRESS_REQUEST_VALID,
4854                 _nvswitch_ctrl_set_ingress_request_valid,
4855                 NVSWITCH_SET_INGRESS_REQUEST_VALID,
4856                 osPrivate, flags);
4857         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4858                 CTRL_NVSWITCH_GET_INGRESS_RESPONSE_TABLE,
4859                 _nvswitch_ctrl_get_ingress_response_table,
4860                 NVSWITCH_GET_INGRESS_RESPONSE_TABLE_PARAMS,
4861                 osPrivate, flags);
4862         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4863                 CTRL_NVSWITCH_SET_INGRESS_RESPONSE_TABLE,
4864                 _nvswitch_ctrl_set_ingress_response_table,
4865                 NVSWITCH_SET_INGRESS_RESPONSE_TABLE,
4866                 osPrivate, flags);
4867         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4868                 CTRL_NVSWITCH_SET_GANGED_LINK_TABLE,
4869                 _nvswitch_ctrl_set_ganged_link_table,
4870                 NVSWITCH_SET_GANGED_LINK_TABLE,
4871                 osPrivate, flags);
4872         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_LATENCY_BINS,
4873                 nvswitch_ctrl_set_latency_bins,
4874                 NVSWITCH_SET_LATENCY_BINS,
4875                 osPrivate, flags);
4876         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4877                 CTRL_NVSWITCH_SET_NVLIPT_COUNTER_CONFIG,
4878                 _nvswitch_ctrl_set_nvlipt_counter_config,
4879                 NVSWITCH_SET_NVLIPT_COUNTER_CONFIG,
4880                 osPrivate, flags);
4881         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4882                 CTRL_NVSWITCH_GET_NVLIPT_COUNTER_CONFIG,
4883                 _nvswitch_ctrl_get_nvlipt_counter_config,
4884                 NVSWITCH_GET_NVLIPT_COUNTER_CONFIG,
4885                 osPrivate, flags);
4886         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_REMAP_POLICY,
4887                 _nvswitch_ctrl_set_remap_policy,
4888                 NVSWITCH_SET_REMAP_POLICY,
4889                 osPrivate, flags);
4890         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_GET_REMAP_POLICY,
4891                 _nvswitch_ctrl_get_remap_policy,
4892                 NVSWITCH_GET_REMAP_POLICY_PARAMS,
4893                 osPrivate, flags);
4894         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4895                 CTRL_NVSWITCH_SET_REMAP_POLICY_VALID,
4896                 _nvswitch_ctrl_set_remap_policy_valid,
4897                 NVSWITCH_SET_REMAP_POLICY_VALID,
4898                 osPrivate, flags);
4899         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_ROUTING_ID,
4900                 _nvswitch_ctrl_set_routing_id,
4901                 NVSWITCH_SET_ROUTING_ID,
4902                 osPrivate, flags);
4903         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_GET_ROUTING_ID,
4904                 _nvswitch_ctrl_get_routing_id,
4905                 NVSWITCH_GET_ROUTING_ID_PARAMS,
4906                 osPrivate, flags);
4907         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_ROUTING_ID_VALID,
4908                 _nvswitch_ctrl_set_routing_id_valid,
4909                 NVSWITCH_SET_ROUTING_LAN_VALID,
4910                 osPrivate, flags);
4911         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_ROUTING_LAN,
4912                 _nvswitch_ctrl_set_routing_lan,
4913                 NVSWITCH_SET_ROUTING_LAN,
4914                 osPrivate, flags);
4915         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_GET_ROUTING_LAN,
4916                 _nvswitch_ctrl_get_routing_lan,
4917                 NVSWITCH_GET_ROUTING_LAN_PARAMS,
4918                 osPrivate, flags);
4919         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4920                 CTRL_NVSWITCH_SET_ROUTING_LAN_VALID,
4921                 _nvswitch_ctrl_set_routing_lan_valid,
4922                 NVSWITCH_SET_ROUTING_LAN_VALID,
4923                 osPrivate, flags);
4924         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4925                 CTRL_NVSWITCH_GET_INGRESS_REQLINKID,
4926                 _nvswitch_ctrl_get_ingress_reqlinkid,
4927                 NVSWITCH_GET_INGRESS_REQLINKID_PARAMS,
4928                 osPrivate, flags);
4929         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_UNREGISTER_LINK,
4930                 _nvswitch_ctrl_unregister_link,
4931                 NVSWITCH_UNREGISTER_LINK_PARAMS,
4932                 osPrivate, flags);
4933         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4934                 CTRL_NVSWITCH_RESET_AND_DRAIN_LINKS,
4935                 _nvswitch_ctrl_reset_and_drain_links,
4936                 NVSWITCH_RESET_AND_DRAIN_LINKS_PARAMS,
4937                 osPrivate, flags);
4938         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_BIOS_INFO,
4939                 _nvswitch_ctrl_get_bios_info,
4940                 NVSWITCH_GET_BIOS_INFO_PARAMS);
4941         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_INFOROM_VERSION,
4942                 _nvswitch_ctrl_get_inforom_version,
4943                 NVSWITCH_GET_INFOROM_VERSION_PARAMS);
4944         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4945                 CTRL_NVSWITCH_BLACKLIST_DEVICE,
4946                 nvswitch_ctrl_blacklist_device,
4947                 NVSWITCH_BLACKLIST_DEVICE_PARAMS,
4948                 osPrivate, flags);
4949         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4950                 CTRL_NVSWITCH_SET_FM_DRIVER_STATE,
4951                 nvswitch_ctrl_set_fm_driver_state,
4952                 NVSWITCH_SET_FM_DRIVER_STATE_PARAMS,
4953                 osPrivate, flags);
4954         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4955                 CTRL_NVSWITCH_SET_DEVICE_FABRIC_STATE,
4956                 nvswitch_ctrl_set_device_fabric_state,
4957                 NVSWITCH_SET_DEVICE_FABRIC_STATE_PARAMS,
4958                 osPrivate, flags);
4959         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4960                 CTRL_NVSWITCH_SET_FM_HEARTBEAT_TIMEOUT,
4961                 nvswitch_ctrl_set_fm_timeout,
4962                 NVSWITCH_SET_FM_HEARTBEAT_TIMEOUT_PARAMS,
4963                 osPrivate, flags);
4964         NVSWITCH_DEV_CMD_DISPATCH_WITH_PRIVATE_DATA(
4965                 CTRL_NVSWITCH_REGISTER_EVENTS,
4966                 _nvswitch_ctrl_register_events,
4967                 NVSWITCH_REGISTER_EVENTS_PARAMS,
4968                 osPrivate);
4969         NVSWITCH_DEV_CMD_DISPATCH_WITH_PRIVATE_DATA(
4970                 CTRL_NVSWITCH_UNREGISTER_EVENTS,
4971                 _nvswitch_ctrl_unregister_events,
4972                 NVSWITCH_UNREGISTER_EVENTS_PARAMS,
4973                 osPrivate);
4974         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4975                 CTRL_NVSWITCH_SET_TRAINING_ERROR_INFO,
4976                 _nvswitch_ctrl_set_training_error_info,
4977                 NVSWITCH_SET_TRAINING_ERROR_INFO_PARAMS,
4978                 osPrivate, flags);
4979         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4980                 CTRL_NVSWITCH_SET_MC_RID_TABLE,
4981                 _nvswitch_ctrl_set_mc_rid_table,
4982                 NVSWITCH_SET_MC_RID_TABLE_PARAMS,
4983                 osPrivate, flags);
4984         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4985                 CTRL_NVSWITCH_GET_MC_RID_TABLE,
4986                 _nvswitch_ctrl_get_mc_rid_table,
4987                 NVSWITCH_GET_MC_RID_TABLE_PARAMS,
4988                 osPrivate, flags);
4989         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4990                 CTRL_NVSWITCH_GET_COUNTERS,
4991                 _nvswitch_ctrl_get_counters,
4992                 NVSWITCH_NVLINK_GET_COUNTERS_PARAMS,
4993                 osPrivate, flags);
4994         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
4995                 CTRL_NVSWITCH_GET_NVLINK_ECC_ERRORS,
4996                 _nvswitch_ctrl_get_nvlink_ecc_errors,
4997                 NVSWITCH_GET_NVLINK_ECC_ERRORS_PARAMS,
4998                 osPrivate, flags);
4999         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
5000                 CTRL_NVSWITCH_I2C_SMBUS_COMMAND,
5001                 _nvswitch_ctrl_i2c_smbus_command,
5002                 NVSWITCH_I2C_SMBUS_COMMAND_PARAMS,
5003                 osPrivate, NVSWITCH_DEV_CMD_CHECK_ADMIN);
5004         NVSWITCH_DEV_CMD_DISPATCH_RESERVED(
5005                 CTRL_NVSWITCH_RESERVED_0);
5006         NVSWITCH_DEV_CMD_DISPATCH_RESERVED(
5007                 CTRL_NVSWITCH_RESERVED_1);
5008         NVSWITCH_DEV_CMD_DISPATCH_RESERVED(
5009                 CTRL_NVSWITCH_RESERVED_2);
5010         NVSWITCH_DEV_CMD_DISPATCH_RESERVED(
5011                 CTRL_NVSWITCH_RESERVED_3);
5012         NVSWITCH_DEV_CMD_DISPATCH_RESERVED(
5013                 CTRL_NVSWITCH_RESERVED_4);
5014         NVSWITCH_DEV_CMD_DISPATCH_RESERVED(
5015                 CTRL_NVSWITCH_RESERVED_5);
5016         NVSWITCH_DEV_CMD_DISPATCH_RESERVED(
5017                 CTRL_NVSWITCH_RESERVED_8);
5018         NVSWITCH_DEV_CMD_DISPATCH_RESERVED(
5019                 CTRL_NVSWITCH_RESERVED_9);
5020         NVSWITCH_DEV_CMD_DISPATCH_RESERVED(
5021                 CTRL_NVSWITCH_RESERVED_10);
5022         NVSWITCH_DEV_CMD_DISPATCH_RESERVED(
5023                 CTRL_NVSWITCH_RESERVED_11);
5024         NVSWITCH_DEV_CMD_DISPATCH(
5025                 CTRL_NVSWITCH_GET_TEMPERATURE_LIMIT,
5026                 _nvswitch_ctrl_therm_get_temperature_limit,
5027                 NVSWITCH_CTRL_GET_TEMPERATURE_LIMIT_PARAMS);
5028         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
5029                 CTRL_NVSWITCH_GET_NVLINK_MAX_ERROR_RATES,
5030                 _nvswitch_ctrl_get_inforom_nvlink_max_correctable_error_rate,
5031                 NVSWITCH_GET_NVLINK_MAX_CORRECTABLE_ERROR_RATES_PARAMS,
5032                 osPrivate, flags);
5033         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
5034                 CTRL_NVSWITCH_GET_NVLINK_ERROR_COUNTS,
5035                 _nvswitch_ctrl_get_inforom_nvlink_errors,
5036                 NVSWITCH_GET_NVLINK_ERROR_COUNTS_PARAMS,
5037                 osPrivate, flags);
5038         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
5039                 CTRL_NVSWITCH_GET_ECC_ERROR_COUNTS,
5040                 _nvswitch_ctrl_get_inforom_ecc_errors,
5041                 NVSWITCH_GET_ECC_ERROR_COUNTS_PARAMS,
5042                 osPrivate, flags);
5043         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
5044                 CTRL_NVSWITCH_GET_SXIDS,
5045                 _nvswitch_ctrl_get_inforom_bbx_sxid,
5046                 NVSWITCH_GET_SXIDS_PARAMS,
5047                 osPrivate, flags);
5048         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
5049                 CTRL_NVSWITCH_GET_FOM_VALUES,
5050                 _nvswitch_ctrl_get_fom_values,
5051                 NVSWITCH_GET_FOM_VALUES_PARAMS,
5052                 osPrivate, flags);
5053         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
5054                 CTRL_NVSWITCH_GET_NVLINK_LP_COUNTERS,
5055                 _nvswitch_ctrl_get_nvlink_lp_counters,
5056                 NVSWITCH_GET_NVLINK_LP_COUNTERS_PARAMS,
5057                 osPrivate, flags);
5058         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_RESIDENCY_BINS,
5059                 _nvswitch_ctrl_get_residency_bins,
5060                 NVSWITCH_GET_RESIDENCY_BINS);
5061         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_RESIDENCY_BINS,
5062                 _nvswitch_ctrl_set_residency_bins,
5063                 NVSWITCH_SET_RESIDENCY_BINS,
5064                 osPrivate, flags);
5065         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_RB_STALL_BUSY,
5066                 _nvswitch_ctrl_get_rb_stall_busy,
5067                 NVSWITCH_GET_RB_STALL_BUSY);
5068         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_MULTICAST_ID_ERROR_VECTOR,
5069                 nvswitch_ctrl_get_multicast_id_error_vector,
5070                 NVSWITCH_GET_MULTICAST_ID_ERROR_VECTOR);
5071         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_CLEAR_MULTICAST_ID_ERROR_VECTOR,
5072                 nvswitch_ctrl_clear_multicast_id_error_vector,
5073                 NVSWITCH_CLEAR_MULTICAST_ID_ERROR_VECTOR);
5074         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
5075                 CTRL_NVSWITCH_INBAND_SEND_DATA,
5076                 _nvswitch_ctrl_inband_send_data,
5077                 NVSWITCH_INBAND_SEND_DATA_PARAMS,
5078                 osPrivate, flags);
5079         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
5080                 CTRL_NVSWITCH_INBAND_READ_DATA,
5081                 _nvswitch_ctrl_inband_read_data,
5082                  NVSWITCH_INBAND_READ_DATA_PARAMS,
5083                 osPrivate, flags);
5084         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
5085                 CTRL_NVSWITCH_INBAND_FLUSH_DATA,
5086                 _nvswitch_ctrl_inband_flush_data,
5087                 NVSWITCH_INBAND_FLUSH_DATA_PARAMS,
5088                 osPrivate, flags);
5089         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
5090                 CTRL_NVSWITCH_INBAND_PENDING_DATA_STATS,
5091                 _nvswitch_ctrl_inband_pending_data_stats,
5092                 NVSWITCH_INBAND_PENDING_DATA_STATS_PARAMS,
5093                 osPrivate, flags);
5094         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_BOARD_PART_NUMBER,
5095                 _nvswitch_ctrl_get_board_part_number,
5096                 NVSWITCH_GET_BOARD_PART_NUMBER_VECTOR);
5097         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(
5098                 CTRL_NVSWITCH_GET_SW_INFO,
5099                 _nvswitch_ctrl_get_sw_info,
5100                 NVSWITCH_GET_SW_INFO_PARAMS,
5101                 osPrivate, flags);
5102         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_REGISTER_READ,
5103                 _nvswitch_ctrl_register_read,
5104                 NVSWITCH_REGISTER_READ,
5105                 osPrivate, flags);
5106         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_REGISTER_WRITE,
5107                 _nvswitch_ctrl_register_write,
5108                 NVSWITCH_REGISTER_WRITE,
5109                 osPrivate, flags);
5110         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_GET_ERR_INFO,
5111                 _nvswitch_ctrl_get_err_info,
5112                 NVSWITCH_NVLINK_GET_ERR_INFO_PARAMS,
5113                 osPrivate, flags);
5114         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_CLEAR_COUNTERS,
5115                 _nvswitch_ctrl_clear_counters,
5116                 NVSWITCH_NVLINK_CLEAR_COUNTERS_PARAMS,
5117                 osPrivate, flags);
5118         NVSWITCH_DEV_CMD_DISPATCH_PRIVILEGED(CTRL_NVSWITCH_SET_NVLINK_ERROR_THRESHOLD,
5119                 _nvswitch_ctrl_set_nvlink_error_threshold,
5120                 NVSWITCH_SET_NVLINK_ERROR_THRESHOLD_PARAMS,
5121                 osPrivate, flags);
5122         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_NVLINK_ERROR_THRESHOLD,
5123                 _nvswitch_ctrl_get_nvlink_error_threshold,
5124                 NVSWITCH_GET_NVLINK_ERROR_THRESHOLD_PARAMS);
5125         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_VOLTAGE,
5126                 _nvswitch_ctrl_therm_read_voltage,
5127                 NVSWITCH_CTRL_GET_VOLTAGE_PARAMS);
5128         NVSWITCH_DEV_CMD_DISPATCH(CTRL_NVSWITCH_GET_POWER,
5129                 _nvswitch_ctrl_therm_read_power,
5130                 NVSWITCH_GET_POWER_PARAMS);
5131 
5132         default:
5133             nvswitch_os_print(NVSWITCH_DBG_LEVEL_INFO, "unknown ioctl %x\n", cmd);
5134             retval = -NVL_BAD_ARGS;
5135             break;
5136     }
5137 
5138     return retval;
5139 }
5140 
5141 #if defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS)
5142 void nvswitch_assert_log
5143 (
5144     const char *function,
5145     const char *file,
5146     NvU32 line
5147 )
5148 {
5149     nvswitch_os_assert_log("NVSwitch: Assertion failed in %s() at %s:%d\n",
5150                            function, file, line);
5151 }
5152 #else
5153 void nvswitch_assert_log(void)
5154 {
5155     nvswitch_os_assert_log("NVSwitch: Assertion failed\n");
5156 }
5157 #endif
5158