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