550.144.03

This commit is contained in:
Bernhard Stoeckner
2025-01-16 17:31:43 +01:00
parent 346011d45c
commit aca429201d
22 changed files with 590 additions and 642 deletions

View File

@@ -1,7 +1,7 @@
# NVIDIA Linux Open GPU Kernel Module Source # NVIDIA Linux Open GPU Kernel Module Source
This is the source release of the NVIDIA Linux open GPU kernel modules, This is the source release of the NVIDIA Linux open GPU kernel modules,
version 550.142. version 550.144.03.
## How to Build ## How to Build
@@ -17,7 +17,7 @@ as root:
Note that the kernel modules built here must be used with GSP Note that the kernel modules built here must be used with GSP
firmware and user-space NVIDIA GPU driver components from a corresponding firmware and user-space NVIDIA GPU driver components from a corresponding
550.142 driver release. This can be achieved by installing 550.144.03 driver release. This can be achieved by installing
the NVIDIA GPU driver from the .run file using the `--no-kernel-modules` the NVIDIA GPU driver from the .run file using the `--no-kernel-modules`
option. E.g., option. E.g.,
@@ -188,7 +188,7 @@ encountered specific to them.
For details on feature support and limitations, see the NVIDIA GPU driver For details on feature support and limitations, see the NVIDIA GPU driver
end user README here: end user README here:
https://us.download.nvidia.com/XFree86/Linux-x86_64/550.142/README/kernel_open.html https://us.download.nvidia.com/XFree86/Linux-x86_64/550.144.03/README/kernel_open.html
For vGPU support, please refer to the README.vgpu packaged in the vGPU Host For vGPU support, please refer to the README.vgpu packaged in the vGPU Host
Package for more details. Package for more details.

View File

@@ -86,7 +86,7 @@ EXTRA_CFLAGS += -I$(src)/common/inc
EXTRA_CFLAGS += -I$(src) EXTRA_CFLAGS += -I$(src)
EXTRA_CFLAGS += -Wall $(DEFINES) $(INCLUDES) -Wno-cast-qual -Wno-format-extra-args EXTRA_CFLAGS += -Wall $(DEFINES) $(INCLUDES) -Wno-cast-qual -Wno-format-extra-args
EXTRA_CFLAGS += -D__KERNEL__ -DMODULE -DNVRM EXTRA_CFLAGS += -D__KERNEL__ -DMODULE -DNVRM
EXTRA_CFLAGS += -DNV_VERSION_STRING=\"550.142\" EXTRA_CFLAGS += -DNV_VERSION_STRING=\"550.144.03\"
ifneq ($(SYSSRCHOST1X),) ifneq ($(SYSSRCHOST1X),)
EXTRA_CFLAGS += -I$(SYSSRCHOST1X) EXTRA_CFLAGS += -I$(SYSSRCHOST1X)

View File

@@ -5583,6 +5583,23 @@ compile_test() {
else else
echo "#undef NV_OF_PROPERTY_READ_VARIABLE_U32_ARRAY_PRESENT" | append_conftest "functions" echo "#undef NV_OF_PROPERTY_READ_VARIABLE_U32_ARRAY_PRESENT" | append_conftest "functions"
fi fi
;;
module_import_ns_takes_string_literal)
#
# Determine if the MODULE_IMPORT_NS macro takes a string literal
# or constant.
#
# Commit cdd30ebb1b9f ("module: Convert symbol namespace to
# string literal") changed MODULE_IMPORT_NS to take a string
# literal in Linux kernel v6.13.
#
CODE="
#include <linux/module.h>
MODULE_IMPORT_NS(DMA_BUF);"
compile_check_conftest "$CODE" "NV_MODULE_IMPORT_NS_TAKES_STRING_LITERAL" "" "functions"
;; ;;
devm_of_platform_populate) devm_of_platform_populate)
@@ -6616,7 +6633,8 @@ compile_test() {
# Determine whether drm_fbdev_ttm_setup is present. # Determine whether drm_fbdev_ttm_setup is present.
# #
# Added by commit aae4682e5d66 ("drm/fbdev-generic: # Added by commit aae4682e5d66 ("drm/fbdev-generic:
# Convert to fbdev-ttm") in v6.11. # Convert to fbdev-ttm") in v6.11. Removed by commit
# 1000634477d8 ("drm/fbdev-ttm:Convert to client-setup") in v6.13.
# #
CODE=" CODE="
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
@@ -6630,6 +6648,25 @@ compile_test() {
compile_check_conftest "$CODE" "NV_DRM_FBDEV_TTM_SETUP_PRESENT" "" "functions" compile_check_conftest "$CODE" "NV_DRM_FBDEV_TTM_SETUP_PRESENT" "" "functions"
;; ;;
drm_client_setup)
#
# Determine whether drm_client_setup is present.
#
# Added by commit d07fdf922592 ("drm/fbdev-ttm:
# Convert to client-setup") in v6.13.
#
CODE="
#include <drm/drm_fb_helper.h>
#if defined(NV_DRM_DRM_CLIENT_SETUP_H_PRESENT)
#include <drm/drm_client_setup.h>
#endif
void conftest_drm_client_setup(void) {
drm_client_setup();
}"
compile_check_conftest "$CODE" "NV_DRM_CLIENT_SETUP_PRESENT" "" "functions"
;;
drm_output_poll_changed) drm_output_poll_changed)
# #
# Determine whether drm_mode_config_funcs.output_poll_changed # Determine whether drm_mode_config_funcs.output_poll_changed
@@ -6653,6 +6690,38 @@ compile_test() {
compile_check_conftest "$CODE" "NV_DRM_OUTPUT_POLL_CHANGED_PRESENT" "" "types" compile_check_conftest "$CODE" "NV_DRM_OUTPUT_POLL_CHANGED_PRESENT" "" "types"
;; ;;
aperture_remove_conflicting_devices)
#
# Determine whether aperture_remove_conflicting_devices is present.
#
# Added by commit 7283f862bd991 ("drm: Implement DRM aperture
# helpers under video/") in v6.0
CODE="
#if defined(NV_LINUX_APERTURE_H_PRESENT)
#include <linux/aperture.h>
#endif
void conftest_aperture_remove_conflicting_devices(void) {
aperture_remove_conflicting_devices();
}"
compile_check_conftest "$CODE" "NV_APERTURE_REMOVE_CONFLICTING_DEVICES_PRESENT" "" "functions"
;;
aperture_remove_conflicting_pci_devices)
#
# Determine whether aperture_remove_conflicting_pci_devices is present.
#
# Added by commit 7283f862bd991 ("drm: Implement DRM aperture
# helpers under video/") in v6.0
CODE="
#if defined(NV_LINUX_APERTURE_H_PRESENT)
#include <linux/aperture.h>
#endif
void conftest_aperture_remove_conflicting_pci_devices(void) {
aperture_remove_conflicting_pci_devices();
}"
compile_check_conftest "$CODE" "NV_APERTURE_REMOVE_CONFLICTING_PCI_DEVICES_PRESENT" "" "functions"
;;
drm_aperture_remove_conflicting_pci_framebuffers) drm_aperture_remove_conflicting_pci_framebuffers)
# #
# Determine whether drm_aperture_remove_conflicting_pci_framebuffers is present. # Determine whether drm_aperture_remove_conflicting_pci_framebuffers is present.
@@ -6746,17 +6815,17 @@ compile_test() {
# This test is not complete and may return false positive. # This test is not complete and may return false positive.
# #
CODE=" CODE="
#include <crypto/akcipher.h> #include <crypto/akcipher.h>
#include <crypto/algapi.h> #include <crypto/algapi.h>
#include <crypto/ecc_curve.h> #include <crypto/ecc_curve.h>
#include <crypto/ecdh.h> #include <crypto/ecdh.h>
#include <crypto/hash.h> #include <crypto/hash.h>
#include <crypto/internal/ecc.h> #include <crypto/internal/ecc.h>
#include <crypto/kpp.h> #include <crypto/kpp.h>
#include <crypto/public_key.h> #include <crypto/public_key.h>
#include <crypto/sm3.h> #include <crypto/sm3.h>
#include <keys/asymmetric-type.h> #include <keys/asymmetric-type.h>
#include <linux/crypto.h> #include <linux/crypto.h>
void conftest_crypto(void) { void conftest_crypto(void) {
struct shash_desc sd; struct shash_desc sd;
struct crypto_shash cs; struct crypto_shash cs;
@@ -6766,6 +6835,47 @@ compile_test() {
compile_check_conftest "$CODE" "NV_CRYPTO_PRESENT" "" "symbols" compile_check_conftest "$CODE" "NV_CRYPTO_PRESENT" "" "symbols"
;; ;;
crypto_akcipher_verify)
#
# Determine whether the crypto_akcipher_verify API is still present.
# It was removed by commit 6b34562 ('crypto: akcipher - Drop sign/verify operations')
# in v6.13-rc1 (2024-10-04).
#
# This test is dependent on the crypto conftest to determine whether crypto should be
# enabled at all. That means that if the kernel is old enough such that crypto_akcipher_verify
#
# The test merely checks for the presence of the API, as it assumes that if the API
# is no longer present, the new API to replace it (crypto_sig_verify) must be present.
# If the kernel version is too old to have crypto_akcipher_verify, it will fail the crypto
# conftest above and all crypto code will be compiled out.
#
CODE="
#include <crypto/akcipher.h>
#include <linux/crypto.h>
void conftest_crypto_akcipher_verify(void) {
(void)crypto_akcipher_verify;
}"
compile_check_conftest "$CODE" "NV_CRYPTO_AKCIPHER_VERIFY_PRESENT" "" "symbols"
;;
ecc_digits_from_bytes)
#
# Determine whether ecc_digits_from_bytes is present.
# It was added in commit c6ab5c915da4 ('crypto: ecc - Prevent ecc_digits_from_bytes from
# reading too many bytes') in v6.10.
#
# This functionality is needed when crypto_akcipher_verify is not present.
#
CODE="
#include <crypto/internal/ecc.h>
void conftest_ecc_digits_from_bytes(void) {
(void)ecc_digits_from_bytes;
}"
compile_check_conftest "$CODE" "NV_ECC_DIGITS_FROM_BYTES_PRESENT" "" "symbols"
;;
mempolicy_has_unified_nodes) mempolicy_has_unified_nodes)
# #
# Determine if the 'mempolicy' structure has # Determine if the 'mempolicy' structure has

View File

@@ -16,6 +16,7 @@ NV_HEADER_PRESENCE_TESTS = \
drm/drm_drv.h \ drm/drm_drv.h \
drm/drm_fbdev_generic.h \ drm/drm_fbdev_generic.h \
drm/drm_fbdev_ttm.h \ drm/drm_fbdev_ttm.h \
drm/drm_client_setup.h \
drm/drm_framebuffer.h \ drm/drm_framebuffer.h \
drm/drm_connector.h \ drm/drm_connector.h \
drm/drm_probe_helper.h \ drm/drm_probe_helper.h \
@@ -33,6 +34,7 @@ NV_HEADER_PRESENCE_TESTS = \
generated/autoconf.h \ generated/autoconf.h \
generated/compile.h \ generated/compile.h \
generated/utsrelease.h \ generated/utsrelease.h \
linux/aperture.h \
linux/efi.h \ linux/efi.h \
linux/kconfig.h \ linux/kconfig.h \
linux/platform/tegra/mc_utils.h \ linux/platform/tegra/mc_utils.h \
@@ -99,5 +101,6 @@ NV_HEADER_PRESENCE_TESTS = \
linux/cc_platform.h \ linux/cc_platform.h \
asm/cpufeature.h \ asm/cpufeature.h \
linux/mpi.h \ linux/mpi.h \
asm/mshyperv.h asm/mshyperv.h \
crypto/sig.h

View File

@@ -62,6 +62,13 @@
#undef NV_DRM_FENCE_AVAILABLE #undef NV_DRM_FENCE_AVAILABLE
#endif #endif
#if defined(NV_DRM_CLIENT_SETUP_PRESENT) && \
(defined(NV_DRM_APERTURE_REMOVE_CONFLICTING_PCI_FRAMEBUFFERS_PRESENT) || \
defined(NV_APERTURE_REMOVE_CONFLICTING_PCI_DEVICES_PRESENT))
#define NV_DRM_FBDEV_AVAILABLE
#define NV_DRM_CLIENT_AVAILABLE
#endif
/* /*
* We can support color management if either drm_helper_crtc_enable_color_mgmt() * We can support color management if either drm_helper_crtc_enable_color_mgmt()
* or drm_crtc_enable_color_mgmt() exist. * or drm_crtc_enable_color_mgmt() exist.

View File

@@ -64,11 +64,22 @@
#include <drm/drm_ioctl.h> #include <drm/drm_ioctl.h>
#endif #endif
#if defined(NV_DRM_FBDEV_AVAILABLE) #if defined(NV_LINUX_APERTURE_H_PRESENT)
#include <linux/aperture.h>
#endif
#if defined(NV_DRM_DRM_APERTURE_H_PRESENT)
#include <drm/drm_aperture.h> #include <drm/drm_aperture.h>
#endif
#if defined(NV_DRM_FBDEV_AVAILABLE)
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
#endif #endif
#if defined(NV_DRM_DRM_CLIENT_SETUP_H_PRESENT)
#include <drm/drm_client_setup.h>
#endif
#if defined(NV_DRM_DRM_FBDEV_TTM_H_PRESENT) #if defined(NV_DRM_DRM_FBDEV_TTM_H_PRESENT)
#include <drm/drm_fbdev_ttm.h> #include <drm/drm_fbdev_ttm.h>
#elif defined(NV_DRM_DRM_FBDEV_GENERIC_H_PRESENT) #elif defined(NV_DRM_DRM_FBDEV_GENERIC_H_PRESENT)
@@ -1726,6 +1737,9 @@ static struct drm_driver nv_drm_driver = {
#elif defined(NV_DRM_DRIVER_HAS_LEGACY_DEV_LIST) #elif defined(NV_DRM_DRIVER_HAS_LEGACY_DEV_LIST)
.legacy_dev_list = LIST_HEAD_INIT(nv_drm_driver.legacy_dev_list), .legacy_dev_list = LIST_HEAD_INIT(nv_drm_driver.legacy_dev_list),
#endif #endif
#if defined(DRM_FBDEV_TTM_DRIVER_OPS)
DRM_FBDEV_TTM_DRIVER_OPS,
#endif
}; };
@@ -1827,13 +1841,21 @@ void nv_drm_register_drm_device(const nv_gpu_info_t *gpu_info)
if (bus_is_pci) { if (bus_is_pci) {
struct pci_dev *pdev = to_pci_dev(device); struct pci_dev *pdev = to_pci_dev(device);
#if defined(NV_DRM_APERTURE_REMOVE_CONFLICTING_PCI_FRAMEBUFFERS_PRESENT)
#if defined(NV_DRM_APERTURE_REMOVE_CONFLICTING_PCI_FRAMEBUFFERS_HAS_DRIVER_ARG) #if defined(NV_DRM_APERTURE_REMOVE_CONFLICTING_PCI_FRAMEBUFFERS_HAS_DRIVER_ARG)
drm_aperture_remove_conflicting_pci_framebuffers(pdev, &nv_drm_driver); drm_aperture_remove_conflicting_pci_framebuffers(pdev, &nv_drm_driver);
#else #else
drm_aperture_remove_conflicting_pci_framebuffers(pdev, nv_drm_driver.name); drm_aperture_remove_conflicting_pci_framebuffers(pdev, nv_drm_driver.name);
#endif #endif
#elif defined(NV_APERTURE_REMOVE_CONFLICTING_PCI_DEVICES_PRESENT)
aperture_remove_conflicting_pci_devices(pdev, nv_drm_driver.name);
#endif
} }
#if defined(NV_DRM_FBDEV_TTM_AVAILABLE) #if defined(NV_DRM_CLIENT_AVAILABLE)
drm_client_setup(dev, NULL);
#elif defined(NV_DRM_FBDEV_TTM_AVAILABLE)
drm_fbdev_ttm_setup(dev, 32); drm_fbdev_ttm_setup(dev, 32);
#elif defined(NV_DRM_FBDEV_GENERIC_AVAILABLE) #elif defined(NV_DRM_FBDEV_GENERIC_AVAILABLE)
drm_fbdev_generic_setup(dev, 32); drm_fbdev_generic_setup(dev, 32);

View File

@@ -66,8 +66,11 @@ NV_CONFTEST_FUNCTION_COMPILE_TESTS += dma_fence_set_error
NV_CONFTEST_FUNCTION_COMPILE_TESTS += fence_set_error NV_CONFTEST_FUNCTION_COMPILE_TESTS += fence_set_error
NV_CONFTEST_FUNCTION_COMPILE_TESTS += sync_file_get_fence NV_CONFTEST_FUNCTION_COMPILE_TESTS += sync_file_get_fence
NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_aperture_remove_conflicting_pci_framebuffers NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_aperture_remove_conflicting_pci_framebuffers
NV_CONFTEST_FUNCTION_COMPILE_TESTS += aperture_remove_conflicting_devices
NV_CONFTEST_FUNCTION_COMPILE_TESTS += aperture_remove_conflicting_pci_devices
NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_fbdev_generic_setup NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_fbdev_generic_setup
NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_fbdev_ttm_setup NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_fbdev_ttm_setup
NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_client_setup
NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_connector_attach_hdr_output_metadata_property NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_connector_attach_hdr_output_metadata_property
NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_helper_crtc_enable_color_mgmt NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_helper_crtc_enable_color_mgmt
NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_crtc_enable_color_mgmt NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_crtc_enable_color_mgmt

View File

@@ -163,7 +163,7 @@ static uvm_va_block_t *hmm_va_block_from_node(uvm_range_tree_node_t *node)
// Copies the contents of the source device-private page to the // Copies the contents of the source device-private page to the
// destination CPU page. This will invalidate mappings, so cannot be // destination CPU page. This will invalidate mappings, so cannot be
// called while holding any va_block locks. // called while holding any va_block locks.
static void hmm_copy_devmem_page(struct page *dst_page, struct page *src_page) static NV_STATUS hmm_copy_devmem_page(struct page *dst_page, struct page *src_page)
{ {
uvm_tracker_t tracker = UVM_TRACKER_INIT(); uvm_tracker_t tracker = UVM_TRACKER_INIT();
uvm_gpu_phys_address_t src_addr; uvm_gpu_phys_address_t src_addr;
@@ -207,7 +207,7 @@ static void hmm_copy_devmem_page(struct page *dst_page, struct page *src_page)
uvm_push_end(&push); uvm_push_end(&push);
status = uvm_tracker_add_push_safe(&tracker, &push); status = uvm_tracker_add_push_safe(&tracker, &push);
if (status == NV_OK) if (status == NV_OK)
uvm_tracker_wait_deinit(&tracker); status = uvm_tracker_wait_deinit(&tracker);
out_unmap_cpu: out_unmap_cpu:
uvm_parent_gpu_unmap_cpu_pages(gpu->parent, dma_addr, PAGE_SIZE); uvm_parent_gpu_unmap_cpu_pages(gpu->parent, dma_addr, PAGE_SIZE);
@@ -216,12 +216,7 @@ out_unmap_gpu:
uvm_mmu_chunk_unmap(gpu_chunk, NULL); uvm_mmu_chunk_unmap(gpu_chunk, NULL);
out: out:
// We can't fail eviction because we need to free the device-private pages return status;
// so the GPU can be unregistered. So the best we can do is warn on any
// failures and zero the uninitialised page. This could result in data loss
// in the application but failures are not expected.
if (WARN_ON(status != NV_OK))
memzero_page(dst_page, 0, PAGE_SIZE);
} }
static NV_STATUS uvm_hmm_pmm_gpu_evict_pfn(unsigned long pfn) static NV_STATUS uvm_hmm_pmm_gpu_evict_pfn(unsigned long pfn)
@@ -246,7 +241,12 @@ static NV_STATUS uvm_hmm_pmm_gpu_evict_pfn(unsigned long pfn)
lock_page(dst_page); lock_page(dst_page);
hmm_copy_devmem_page(dst_page, migrate_pfn_to_page(src_pfn)); // We can't fail eviction because we need to free the device-private
// pages so the GPU can be unregistered. So the best we can do is warn
// on any failures and zero the uninitialized page. This could result
// in data loss in the application but failures are not expected.
if (hmm_copy_devmem_page(dst_page, migrate_pfn_to_page(src_pfn)) != NV_OK)
memzero_page(dst_page, 0, PAGE_SIZE);
dst_pfn = migrate_pfn(page_to_pfn(dst_page)); dst_pfn = migrate_pfn(page_to_pfn(dst_page));
migrate_device_pages(&src_pfn, &dst_pfn, 1); migrate_device_pages(&src_pfn, &dst_pfn, 1);
} }
@@ -3487,12 +3487,17 @@ NV_STATUS uvm_hmm_remote_cpu_fault(struct vm_fault *vmf)
lock_page(dst_page); lock_page(dst_page);
dst_pfn = migrate_pfn(page_to_pfn(dst_page)); dst_pfn = migrate_pfn(page_to_pfn(dst_page));
hmm_copy_devmem_page(dst_page, src_page); status = hmm_copy_devmem_page(dst_page, src_page);
if (status != NV_OK) {
unlock_page(dst_page);
__free_page(dst_page);
dst_pfn = 0;
}
} }
migrate_vma_pages(&args);
out: out:
if (status == NV_OK)
migrate_vma_pages(&args);
migrate_vma_finalize(&args); migrate_vma_finalize(&args);
return status; return status;

View File

@@ -64,7 +64,9 @@
* old or even just user disabled. If we should use LKCA, include headers, else * old or even just user disabled. If we should use LKCA, include headers, else
* define stubs to return errors. * define stubs to return errors.
*/ */
#if defined(NV_CRYPTO_PRESENT) && defined (NV_CONFIG_CRYPTO_PRESENT) #if defined(NV_CRYPTO_PRESENT) && defined (NV_CONFIG_CRYPTO_PRESENT) && \
(defined(NV_CRYPTO_AKCIPHER_VERIFY_PRESENT) || \
(defined(NV_CRYPTO_SIG_H_PRESENT) && defined(NV_ECC_DIGITS_FROM_BYTES_PRESENT)))
#define USE_LKCA 1 #define USE_LKCA 1
#endif #endif

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
@@ -30,14 +30,26 @@ MODULE_SOFTDEP("pre: ecdh_generic,ecdsa_generic");
#include <crypto/akcipher.h> #include <crypto/akcipher.h>
#include <crypto/ecdh.h> #include <crypto/ecdh.h>
#include <crypto/internal/ecc.h> #include <crypto/internal/ecc.h>
#ifndef NV_CRYPTO_AKCIPHER_VERIFY_PRESENT
#include <crypto/sig.h>
struct signature
{
u64 r[ECC_MAX_DIGITS];
u64 s[ECC_MAX_DIGITS];
};
#endif // NV_CRYPTO_AKCIPHER_VERIFY_PRESENT
#define ECDSA_PUBKEY_HEADER_XY_PRESENT (0x4)
struct ecc_ctx { struct ecc_ctx {
unsigned int curve_id; unsigned int curve_id;
u64 priv_key[ECC_MAX_DIGITS]; // In big endian u64 priv_key[ECC_MAX_DIGITS]; // In big endian
struct { struct {
// ecdsa wants byte preceding pub_key to be set to '4' // ecdsa pubkey has header indicating length of pubkey
u64 pub_key_prefix; u8 padding[7];
u8 pub_key_prefix;
u64 pub_key[2 * ECC_MAX_DIGITS]; u64 pub_key[2 * ECC_MAX_DIGITS];
}; };
@@ -46,7 +58,7 @@ struct ecc_ctx {
char const *name; char const *name;
int size; int size;
}; };
#endif #endif // USE_LKCA
void *libspdm_ec_new_by_nid(size_t nid) void *libspdm_ec_new_by_nid(size_t nid)
{ {
@@ -77,7 +89,7 @@ void *libspdm_ec_new_by_nid(size_t nid)
ctx->priv_key_set = false; ctx->priv_key_set = false;
return ctx; return ctx;
#endif #endif // USE_LKCA
} }
void libspdm_ec_free(void *ec_context) void libspdm_ec_free(void *ec_context)
@@ -109,7 +121,7 @@ bool lkca_ecdsa_set_priv_key(void *context, uint8_t *key, size_t key_size)
ctx->pub_key_set = true; ctx->pub_key_set = true;
ctx->priv_key_set = true; ctx->priv_key_set = true;
return true; return true;
#endif #endif // USE_LKCA
} }
bool lkca_ec_set_pub_key(void *ec_context, const uint8_t *public_key, bool lkca_ec_set_pub_key(void *ec_context, const uint8_t *public_key,
@@ -139,7 +151,7 @@ bool lkca_ec_set_pub_key(void *ec_context, const uint8_t *public_key,
memcpy(ctx->pub_key, public_key, public_key_size); memcpy(ctx->pub_key, public_key, public_key_size);
ctx->pub_key_set = true; ctx->pub_key_set = true;
return true; return true;
#endif #endif // USE_LKCA
} }
bool lkca_ec_get_pub_key(void *ec_context, uint8_t *public_key, bool lkca_ec_get_pub_key(void *ec_context, uint8_t *public_key,
@@ -158,7 +170,7 @@ bool lkca_ec_get_pub_key(void *ec_context, uint8_t *public_key,
memcpy(public_key, ctx->pub_key, ctx->size); memcpy(public_key, ctx->pub_key, ctx->size);
return true; return true;
#endif #endif // USE_LKCA
} }
bool lkca_ec_generate_key(void *ec_context, uint8_t *public_data, bool lkca_ec_generate_key(void *ec_context, uint8_t *public_data,
@@ -185,7 +197,7 @@ bool lkca_ec_generate_key(void *ec_context, uint8_t *public_data,
ctx->pub_key_set = true; ctx->pub_key_set = true;
return true; return true;
#endif #endif // USE_LKCA
} }
bool lkca_ec_compute_key(void *ec_context, const uint8_t *peer_public, bool lkca_ec_compute_key(void *ec_context, const uint8_t *peer_public,
@@ -218,28 +230,87 @@ bool lkca_ec_compute_key(void *ec_context, const uint8_t *peer_public,
*key_size = ctx->size / 2; *key_size = ctx->size / 2;
return true; return true;
#endif #endif // USE_LKCA
} }
bool lkca_ecdsa_verify(void *ec_context, size_t hash_nid, #ifndef NV_CRYPTO_AKCIPHER_VERIFY_PRESENT
const uint8_t *message_hash, size_t hash_size, static bool lkca_ecdsa_verify_crypto_sig(void *ec_context, size_t hash_nid,
const uint8_t *signature, size_t sig_size) const uint8_t *message_hash, size_t hash_size,
const uint8_t *signature, size_t sig_size)
{ {
#ifndef USE_LKCA #ifndef USE_LKCA
return false; return false;
#else #else // USE_LKCA
struct ecc_ctx *ctx = ec_context; struct ecc_ctx *ctx = ec_context;
u8 *pub_key;
int err;
DECLARE_CRYPTO_WAIT(wait);
struct crypto_sig * tfm = NULL;
struct signature sig;
if (sig_size != ctx->size || !ctx->pub_key_set)
{
return false;
}
tfm = crypto_alloc_sig(ctx->name, CRYPTO_ALG_TYPE_SIG, 0);
if (IS_ERR(tfm)) {
pr_info("crypto_alloc_sig failed in lkca_ecdsa_verify\n");
return false;
}
// modify header of pubkey to indicate size
pub_key = (u8 *) &(ctx->pub_key_prefix);
*pub_key = ECDSA_PUBKEY_HEADER_XY_PRESENT;
err = crypto_sig_set_pubkey(tfm, pub_key, ctx->size + 1);
if (err != 0)
{
pr_info("crypto_sig_set_pubkey failed in lkca_ecdsa_verify: %d", -err);
goto failTfm;
}
//
// Compared to the way we receive the signature, we need to:
// - swap order of all digits
// - swap endianness for each digit
//
memset(&sig, 0, sizeof(sig));
ecc_digits_from_bytes(signature, ctx->size/2, sig.r, ECC_MAX_DIGITS);
ecc_digits_from_bytes(signature + ctx->size/2, ctx->size/2, sig.s, ECC_MAX_DIGITS);
err = crypto_sig_verify(tfm, (void *)&sig, sizeof(sig), message_hash, hash_size);
if (err != 0)
{
pr_info("crypto_sig_verify failed in lkca_ecdsa_verify %d\n", -err);
}
failTfm:
crypto_free_sig(tfm);
return err == 0;
#endif // USE_LKCA
}
#else // NV_CRYPTO_AKCIPHER_VERIFY_PRESENT
static bool lkca_ecdsa_verify_akcipher(void *ec_context, size_t hash_nid,
const uint8_t *message_hash, size_t hash_size,
const uint8_t *signature, size_t sig_size)
{
#ifndef USE_LKCA
return false;
#else // USE_LKCA
struct ecc_ctx *ctx = ec_context;
u8 *pub_key;
int err;
DECLARE_CRYPTO_WAIT(wait);
// Roundabout way // Roundabout way
u64 ber_max_len = 3 + 2 * (4 + (ECC_MAX_BYTES)); u64 ber_max_len = 3 + 2 * (4 + (ECC_MAX_BYTES));
u64 ber_len = 0; u64 ber_len = 0;
u8 *ber = NULL; u8 *ber = NULL;
u8 *pub_key;
struct akcipher_request *req = NULL; struct akcipher_request *req = NULL;
struct crypto_akcipher *tfm = NULL; struct crypto_akcipher *tfm = NULL;
struct scatterlist sg; struct scatterlist sg;
DECLARE_CRYPTO_WAIT(wait);
int err;
if (sig_size != ctx->size) { if (sig_size != ctx->size) {
return false; return false;
@@ -251,21 +322,21 @@ bool lkca_ecdsa_verify(void *ec_context, size_t hash_nid,
tfm = crypto_alloc_akcipher(ctx->name, CRYPTO_ALG_TYPE_AKCIPHER, 0); tfm = crypto_alloc_akcipher(ctx->name, CRYPTO_ALG_TYPE_AKCIPHER, 0);
if (IS_ERR(tfm)) { if (IS_ERR(tfm)) {
pr_info("ALLOC FAILED\n"); pr_info("crypto_alloc_akcipher failed in lkca_ecdsa_verify\n");
return false; return false;
} }
pub_key = (u8 *) ctx->pub_key; // modify header of pubkey to indicate size
pub_key--; // Go back into byte of pub_key_prefix pub_key = (u8 *) &(ctx->pub_key_prefix);
*pub_key = 4; // And set it to 4 to placate kernel *pub_key = ECDSA_PUBKEY_HEADER_XY_PRESENT;
if ((err = crypto_akcipher_set_pub_key(tfm, pub_key, ctx->size + 1)) != 0) { if ((err = crypto_akcipher_set_pub_key(tfm, pub_key, ctx->size + 1)) != 0) {
pr_info("SET PUB KEY FAILED: %d\n", -err); pr_info("crypto_akcipher_set_pub_key failed in lkca_ecdsa_verify: %d\n", -err);
goto failTfm; goto failTfm;
} }
req = akcipher_request_alloc(tfm, GFP_KERNEL); req = akcipher_request_alloc(tfm, GFP_KERNEL);
if (IS_ERR(req)) { if (IS_ERR(req)) {
pr_info("REQUEST ALLOC FAILED\n"); pr_info("akcipher_request_alloc failed in lkca_ecdsa_verify\n");
goto failTfm; goto failTfm;
} }
@@ -310,9 +381,8 @@ bool lkca_ecdsa_verify(void *ec_context, size_t hash_nid,
CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done, &wait); CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done, &wait);
akcipher_request_set_crypt(req, &sg, NULL, ber_len, hash_size); akcipher_request_set_crypt(req, &sg, NULL, ber_len, hash_size);
err = crypto_wait_req(crypto_akcipher_verify(req), &wait); err = crypto_wait_req(crypto_akcipher_verify(req), &wait);
if (err != 0){ if (err != 0){
pr_info("Verify FAILED %d\n", -err); pr_info("crypto_akcipher_verify failed in lkca_ecdsa_verify %d\n", -err);
} }
kfree(ber); kfree(ber);
@@ -322,5 +392,19 @@ failTfm:
crypto_free_akcipher(tfm); crypto_free_akcipher(tfm);
return err == 0; return err == 0;
#endif #endif // USE_LKCA
}
#endif // NV_CRYPTO_AKCIPHER_VERIFY_PRESENT
bool lkca_ecdsa_verify(void *ec_context, size_t hash_nid,
const uint8_t *message_hash, size_t hash_size,
const uint8_t *signature, size_t sig_size)
{
#ifndef NV_CRYPTO_AKCIPHER_VERIFY_PRESENT
return lkca_ecdsa_verify_crypto_sig(ec_context, hash_nid, message_hash, hash_size,
signature, sig_size);
#else // NV_CRYPTO_AKCIPHER_VERIFY_PRESENT
return lkca_ecdsa_verify_akcipher(ec_context, hash_nid, message_hash, hash_size,
signature, sig_size);
#endif // NV_CRYPTO_AKCIPHER_VERIFY_PRESENT
} }

View File

@@ -127,7 +127,11 @@ MODULE_ALIAS_CHARDEV_MAJOR(NV_MAJOR_DEVICE_NUMBER);
* DMA_BUF namespace is added by commit id 16b0314aa746 * DMA_BUF namespace is added by commit id 16b0314aa746
* ("dma-buf: move dma-buf symbols into the DMA_BUF module namespace") in 5.16 * ("dma-buf: move dma-buf symbols into the DMA_BUF module namespace") in 5.16
*/ */
#if defined(NV_MODULE_IMPORT_NS_TAKES_STRING_LITERAL)
MODULE_IMPORT_NS("DMA_BUF");
#else
MODULE_IMPORT_NS(DMA_BUF); MODULE_IMPORT_NS(DMA_BUF);
#endif
#endif // defined(MODULE_IMPORT_NS) #endif // defined(MODULE_IMPORT_NS)
const NvBool nv_is_rm_firmware_supported_os = NV_TRUE; const NvBool nv_is_rm_firmware_supported_os = NV_TRUE;

View File

@@ -195,6 +195,7 @@ NV_CONFTEST_FUNCTION_COMPILE_TESTS += get_task_ioprio
NV_CONFTEST_FUNCTION_COMPILE_TESTS += mdev_set_iommu_device NV_CONFTEST_FUNCTION_COMPILE_TESTS += mdev_set_iommu_device
NV_CONFTEST_FUNCTION_COMPILE_TESTS += offline_and_remove_memory NV_CONFTEST_FUNCTION_COMPILE_TESTS += offline_and_remove_memory
NV_CONFTEST_FUNCTION_COMPILE_TESTS += crypto_tfm_ctx_aligned NV_CONFTEST_FUNCTION_COMPILE_TESTS += crypto_tfm_ctx_aligned
NV_CONFTEST_FUNCTION_COMPILE_TESTS += module_import_ns_takes_string_literal
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_gpl_of_node_to_nid NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_gpl_of_node_to_nid
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_gpl_sme_active NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_gpl_sme_active
@@ -227,8 +228,10 @@ NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tsec_comms_alloc_me
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tsec_comms_free_gscco_mem NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tsec_comms_free_gscco_mem
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_memory_block_size_bytes NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_memory_block_size_bytes
NV_CONFTEST_SYMBOL_COMPILE_TESTS += crypto NV_CONFTEST_SYMBOL_COMPILE_TESTS += crypto
NV_CONFTEST_SYMBOL_COMPILE_TESTS += crypto_akcipher_verify
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_follow_pte NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_follow_pte
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_gpl_pci_ats_supported NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_gpl_pci_ats_supported
NV_CONFTEST_SYMBOL_COMPILE_TESTS += ecc_digits_from_bytes
NV_CONFTEST_TYPE_COMPILE_TESTS += dma_ops NV_CONFTEST_TYPE_COMPILE_TESTS += dma_ops
NV_CONFTEST_TYPE_COMPILE_TESTS += swiotlb_dma_ops NV_CONFTEST_TYPE_COMPILE_TESTS += swiotlb_dma_ops

View File

@@ -36,25 +36,25 @@
// and then checked back in. You cannot make changes to these sections without // and then checked back in. You cannot make changes to these sections without
// corresponding changes to the buildmeister script // corresponding changes to the buildmeister script
#ifndef NV_BUILD_BRANCH #ifndef NV_BUILD_BRANCH
#define NV_BUILD_BRANCH r550_00 #define NV_BUILD_BRANCH r553_54
#endif #endif
#ifndef NV_PUBLIC_BRANCH #ifndef NV_PUBLIC_BRANCH
#define NV_PUBLIC_BRANCH r550_00 #define NV_PUBLIC_BRANCH r553_54
#endif #endif
#if defined(NV_LINUX) || defined(NV_BSD) || defined(NV_SUNOS) #if defined(NV_LINUX) || defined(NV_BSD) || defined(NV_SUNOS)
#define NV_BUILD_BRANCH_VERSION "rel/gpu_drv/r550/r550_00-505" #define NV_BUILD_BRANCH_VERSION "rel/gpu_drv/r550/r553_54-516"
#define NV_BUILD_CHANGELIST_NUM (35247928) #define NV_BUILD_CHANGELIST_NUM (35333542)
#define NV_BUILD_TYPE "Official" #define NV_BUILD_TYPE "Official"
#define NV_BUILD_NAME "rel/gpu_drv/r550/r550_00-505" #define NV_BUILD_NAME "rel/gpu_drv/r550/r553_54-516"
#define NV_LAST_OFFICIAL_CHANGELIST_NUM (35247928) #define NV_LAST_OFFICIAL_CHANGELIST_NUM (35333542)
#else /* Windows builds */ #else /* Windows builds */
#define NV_BUILD_BRANCH_VERSION "r550_00-470" #define NV_BUILD_BRANCH_VERSION "r553_54-2"
#define NV_BUILD_CHANGELIST_NUM (35247928) #define NV_BUILD_CHANGELIST_NUM (35311700)
#define NV_BUILD_TYPE "Official" #define NV_BUILD_TYPE "Official"
#define NV_BUILD_NAME "553.50" #define NV_BUILD_NAME "553.56"
#define NV_LAST_OFFICIAL_CHANGELIST_NUM (35247928) #define NV_LAST_OFFICIAL_CHANGELIST_NUM (35311700)
#define NV_BUILD_BRANCH_BASE_VERSION R550 #define NV_BUILD_BRANCH_BASE_VERSION R550
#endif #endif
// End buildmeister python edited section // End buildmeister python edited section

View File

@@ -4,7 +4,7 @@
#if defined(NV_LINUX) || defined(NV_BSD) || defined(NV_SUNOS) || defined(NV_VMWARE) || defined(NV_QNX) || defined(NV_INTEGRITY) || \ #if defined(NV_LINUX) || defined(NV_BSD) || defined(NV_SUNOS) || defined(NV_VMWARE) || defined(NV_QNX) || defined(NV_INTEGRITY) || \
(defined(RMCFG_FEATURE_PLATFORM_GSP) && RMCFG_FEATURE_PLATFORM_GSP == 1) (defined(RMCFG_FEATURE_PLATFORM_GSP) && RMCFG_FEATURE_PLATFORM_GSP == 1)
#define NV_VERSION_STRING "550.142" #define NV_VERSION_STRING "550.144.03"
#else #else

View File

@@ -0,0 +1,71 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __dev_nv_pcfg_xve_regmap_h__
#define __dev_nv_pcfg_xve_regmap_h__
#define NV_PCFG_XVE_REGISTER_MAP_START_OFFSET 0x00088000
/*
* <prefix>_MAP has 1 bit set for each dword register.
* <prefix>_COUNT has total number of set bits in <prefix>_MAP.
*/
#define NV_PCFG_XVE_REGISTER_VALID_COUNT 445
#define NV_PCFG_XVE_REGISTER_VALID_MAP { \
/* 0x00088000 */ 0xFFF1FFFF, 0x139FFF9F, \
/* 0x00088100 */ 0x1FBA3C7F, 0x00000000, \
/* 0x00088200 */ 0x03F00000, 0x00000000, \
/* 0x00088300 */ 0x00000000, 0x00000000, \
/* 0x00088400 */ 0x8007FFC0, 0x3F3F5807, \
/* 0x00088500 */ 0x000000BF, 0x00000000, \
/* 0x00088600 */ 0x0140AA1F, 0x00000000, \
/* 0x00088700 */ 0x0001FFFF, 0x00000000, \
/* 0x00088800 */ 0xFFEFDFD7, 0x1EDAFFFF, \
/* 0x00088900 */ 0xFFFFFFFF, 0x000FFFFF, \
/* 0x00088A00 */ 0xFF7FFFFF, 0x0007FFFF, \
/* 0x00088B00 */ 0x00000000, 0xFFFFF000, \
/* 0x00088C00 */ 0x0007BFE7, 0xFFFFFFFC, \
/* 0x00088D00 */ 0xFFFFFFFF, 0x7FFF3FFF, \
/* 0x00088E00 */ 0x000007FF, 0x00000000, \
/* 0x00088F00 */ 0x00000000, 0xFC000000 }
#define NV_PCFG_XVE_REGISTER_WR_COUNT 321
#define NV_PCFG_XVE_REGISTER_WR_MAP { \
/* 0x00088000 */ 0x3EF193FA, 0x1187C505, \
/* 0x00088100 */ 0x1FBA0828, 0x00000000, \
/* 0x00088200 */ 0x03200000, 0x00000000, \
/* 0x00088300 */ 0x00000000, 0x00000000, \
/* 0x00088400 */ 0x80007EC0, 0x3F075007, \
/* 0x00088500 */ 0x000000BF, 0x00000000, \
/* 0x00088600 */ 0x0140AA10, 0x00000000, \
/* 0x00088700 */ 0x0001FFFF, 0x00000000, \
/* 0x00088800 */ 0x004C5FC3, 0x1C5AFFC0, \
/* 0x00088900 */ 0xFFFC7804, 0x000FFFFF, \
/* 0x00088A00 */ 0xFF7FFDFD, 0x00007FFF, \
/* 0x00088B00 */ 0x00000000, 0xF8A54000, \
/* 0x00088C00 */ 0x00003C01, 0x3FFFFFFC, \
/* 0x00088D00 */ 0xFFFFFFFC, 0x739B2C3F, \
/* 0x00088E00 */ 0x000007F8, 0x00000000, \
/* 0x00088F00 */ 0x00000000, 0xFC000000 }
#endif // {__dev_nv_pcfg_xve_regmap_h__}

View File

@@ -209,38 +209,43 @@ _nvswitch_mc_print_directives
} }
#endif // defined(NVSWITCH_MC_TRACE) #endif // defined(NVSWITCH_MC_TRACE)
//
// Build column-port bitmap. Each 32-bit portmap in the array represents a column. // build column-port array
// Each bit set in the portmap represents the column-relative port offset.
//
static NvlStatus static NvlStatus
_nvswitch_mc_build_cpb _nvswitch_mc_build_ports_array
( (
nvswitch_device *device, nvswitch_device *device,
NvU32 num_ports, NvU32 num_ports,
NvU32 *spray_group, NvU32 *spray_group,
NvU32 num_columns, NVSWITCH_COLUMN_PORT_OFFSET_LS10 *ports,
NvU32 *cpb,
NvU8 *vchop_array_sg, NvU8 *vchop_array_sg,
NvU8 vchop_map[NVSWITCH_MC_NUM_COLUMNS_LS10][NVSWITCH_MC_PORTS_PER_COLUMN_LS10] NvU8 vchop_map[NVSWITCH_MC_NUM_COLUMNS_LS10][NVSWITCH_MC_PORTS_PER_COLUMN_LS10]
) )
{ {
NvU64 ports_used = 0;
NvU32 i, ret; NvU32 i, ret;
NVSWITCH_COLUMN_PORT_OFFSET_LS10 cpo; NVSWITCH_COLUMN_PORT_OFFSET_LS10 cpo;
if ((spray_group == NULL) || (ports == NULL) || (num_ports == 0) ||
if ((spray_group == NULL) || (cpb == NULL) || (num_ports == 0) || (num_ports > NVSWITCH_MC_TCP_LIST_SIZE_LS10))
(num_ports > NVSWITCH_NUM_LINKS_LS10))
{ {
NVSWITCH_PRINT(device, ERROR, "%s: invalid arguments\n", __FUNCTION__); NVSWITCH_PRINT(device, ERROR, "%s: invalid arguments\n", __FUNCTION__);
return -NVL_BAD_ARGS; return -NVL_BAD_ARGS;
} }
nvswitch_os_memset(cpb, 0, sizeof(*cpb) * num_columns);
nvswitch_os_memset(vchop_map, 0, sizeof(NvU8) * nvswitch_os_memset(vchop_map, 0, sizeof(NvU8) *
NVSWITCH_MC_NUM_COLUMNS_LS10 * NVSWITCH_MC_PORTS_PER_COLUMN_LS10); NVSWITCH_MC_NUM_COLUMNS_LS10 * NVSWITCH_MC_PORTS_PER_COLUMN_LS10);
for (i = 0; i < num_ports; i++) for (i = 0; i < num_ports; i++)
{ {
// prevent duplicate ports
if (ports_used & NVBIT64(spray_group[i]))
{
NVSWITCH_PRINT(device, ERROR, "%s: duplicate port specified: %d\n", __FUNCTION__,
spray_group[i]);
return -NVL_BAD_ARGS;
}
ports_used |= NVBIT64(spray_group[i]);
ret = _nvswitch_get_column_port_offset_ls10(spray_group[i], &cpo); ret = _nvswitch_get_column_port_offset_ls10(spray_group[i], &cpo);
if (ret != NVL_SUCCESS) if (ret != NVL_SUCCESS)
{ {
@@ -248,14 +253,7 @@ _nvswitch_mc_build_cpb
return ret; return ret;
} }
if (nvswitch_test_flags(cpb[cpo.column], NVBIT(cpo.port_offset))) ports[i] = cpo;
{
NVSWITCH_PRINT(device, ERROR, "%s: duplicate port specified: %d\n", __FUNCTION__,
spray_group[i]);
return -NVL_BAD_ARGS;
}
nvswitch_set_flags(&cpb[cpo.column], NVBIT(cpo.port_offset));
if (vchop_array_sg[i] > NVSWITCH_MC_VCHOP_FORCE1) if (vchop_array_sg[i] > NVSWITCH_MC_VCHOP_FORCE1)
{ {
@@ -263,8 +261,6 @@ _nvswitch_mc_build_cpb
vchop_array_sg[i]); vchop_array_sg[i]);
return -NVL_BAD_ARGS; return -NVL_BAD_ARGS;
} }
vchop_map[cpo.column][cpo.port_offset] = vchop_array_sg[i]; vchop_map[cpo.column][cpo.port_offset] = vchop_array_sg[i];
} }
@@ -297,80 +293,6 @@ _is_primary_replica
return NV_FALSE; return NV_FALSE;
} }
//
// This function compacts the directive list and updates port_list_size
//
static NvlStatus
_nvswitch_mc_compact_portlist
(
nvswitch_device *device,
NVSWITCH_TCP_DIRECTIVE_LS10 *port_list,
NvU32 *port_list_size
)
{
NvU32 cur_portlist_pos, new_portlist_pos;
NVSWITCH_TCP_DIRECTIVE_LS10 *cur_dir, *old_list;
if (port_list_size == NULL)
{
NVSWITCH_PRINT(device, ERROR, "%s: port list size ptr is null\n", __FUNCTION__);
return -NVL_BAD_ARGS;
}
if ((port_list == NULL) || (*port_list_size == 0))
return NVL_SUCCESS;
if ((*port_list_size) > NVSWITCH_MC_TCP_LIST_SIZE_LS10)
{
NVSWITCH_PRINT(device, ERROR, "%s: port list size out of range\n", __FUNCTION__);
return -NVL_BAD_ARGS;
}
#ifdef NVSWITCH_MC_DEBUG
NVSWITCH_PRINT(device, INFO, "%s: old size: %d\n", __FUNCTION__, *port_list_size);
#endif
// create temporary directive list
old_list = nvswitch_os_malloc(sizeof(NVSWITCH_TCP_DIRECTIVE_LS10) * (*port_list_size));
if (!old_list)
{
NVSWITCH_PRINT(device, ERROR, "%s: error allocating temporary portlist\n", __FUNCTION__);
return -NVL_NO_MEM;
}
nvswitch_os_memcpy(old_list, port_list, sizeof(NVSWITCH_TCP_DIRECTIVE_LS10) * (*port_list_size));
// rebuild list using only valid entries
new_portlist_pos = 0;
for (cur_portlist_pos = 0; cur_portlist_pos < (*port_list_size); cur_portlist_pos++)
{
cur_dir = &old_list[cur_portlist_pos];
if (cur_dir->tcp != NVSWITCH_MC_INVALID)
{
#ifdef NVSWITCH_MC_TRACE
NVSWITCH_PRINT(device, INFO, "%s: valid directive:\n", __FUNCTION__);
_nvswitch_mc_print_directive(device, &old_list[cur_portlist_pos]);
#endif
nvswitch_os_memcpy(&port_list[new_portlist_pos], &old_list[cur_portlist_pos],
sizeof(NVSWITCH_TCP_DIRECTIVE_LS10));
new_portlist_pos++;
}
}
nvswitch_os_free(old_list);
#ifdef NVSWITCH_MC_DEBUG
NVSWITCH_PRINT(device, INFO, "%s: new size: %d\n", __FUNCTION__, new_portlist_pos);
#endif
*port_list_size = new_portlist_pos;
return NVL_SUCCESS;
}
// //
// Set the round flags to indicate the size of each multicast round. // Set the round flags to indicate the size of each multicast round.
// See IAS section "6.12. Consistent MC Semantics" for more info. // See IAS section "6.12. Consistent MC Semantics" for more info.
@@ -484,118 +406,13 @@ _nvswitch_mc_set_port_flags
} }
} }
//
// This function "pops" the next port offset from the portlist bitmap.
//
static NV_INLINE NvU8
_nvswitch_mc_get_next_port
(
NvU32 *portmap
)
{
NvU32 port;
if (!portmap)
{
NVSWITCH_ASSERT(0);
return NVSWITCH_MC_NULL_PORT_LS10;
}
//
// We have to do some gymnastics here because LOWESTBITIDX_32 is
// destructive on the input variable, and the result is not assignable.
//
port = *portmap;
LOWESTBITIDX_32(port);
nvswitch_clear_flags(portmap, NVBIT(port));
if (port >= NVSWITCH_MC_PORTS_PER_COLUMN_LS10)
{
NVSWITCH_ASSERT(0);
return NVSWITCH_MC_NULL_PORT_LS10;
}
return (NvU8)port;
}
//
// This helper function generates a map of directive list offsets indexed by tile/column pair
// port offsets. This is used during construction of the directive list to point to where each
// newly constructed directive will be placed in the list. This process has to account for the
// fact that the middle two columns contain 10 ports each, while the rest have 11, all mapping
// into a 32-entry directive list.
//
static NV_INLINE void
_nvswitch_mc_build_mcplist_position_map
(
NvU32 port_offsets_by_tcp[NVSWITCH_MC_NUM_COLUMN_PAIRS_LS10][NVSWITCH_MC_PORTS_PER_COLUMN_LS10]
)
{
NvU32 i, j, tcp;
if (!port_offsets_by_tcp)
{
NVSWITCH_ASSERT(0);
return;
}
for (tcp = 0; tcp < NVSWITCH_MC_NUM_COLUMN_PAIRS_LS10; tcp++)
{
if (tcp == 0)
{
j = 0;
for (i = 0; i < NVSWITCH_MC_PORTS_PER_COLUMN_LS10; i++)
{
port_offsets_by_tcp[tcp][i] = j;
j += NVSWITCH_MC_NUM_COLUMN_PAIRS_LS10;
}
}
if (tcp == 1)
{
j = 1;
for (i = 0; i < NVSWITCH_MC_PORTS_PER_COLUMN_LS10 - 1; i++)
{
port_offsets_by_tcp[tcp][i] = j;
j += NVSWITCH_MC_NUM_COLUMN_PAIRS_LS10;
}
}
if (tcp == 2)
{
j = 2;
for (i = 0; i < NVSWITCH_MC_PORTS_PER_COLUMN_LS10; i++)
{
port_offsets_by_tcp[tcp][i] = (j == NVSWITCH_MC_TCP_LIST_SIZE_LS10) ?
(NVSWITCH_MC_TCP_LIST_SIZE_LS10 - 1) : j;
j += NVSWITCH_MC_NUM_COLUMN_PAIRS_LS10;
}
}
}
}
//
// Wrapper for the NUMSETBITS_32 macro, which is destructive on input.
//
static NV_INLINE NvU32
_nvswitch_mc_get_pop_count
(
NvU32 i
)
{
NvU32 tmp = i;
NUMSETBITS_32(tmp);
return tmp;
}
// //
// Build a list of TCP directives. This is the main conversion function which is used to build a // Build a list of TCP directives. This is the main conversion function which is used to build a
// TCP directive list for each spray group from a given column/port bitmap. // TCP directive list for each spray group from a given column/port bitmap.
// //
// @param device [in] pointer to the nvswitch device struct // @param device [in] pointer to the nvswitch device struct
// @param cpb [in] pointer to the column/port bitmap used to build directive list // @param num_ports [in] number of ports
// @param ports [in] ports array (pair of column and port offset)
// @param primary_replica [in] the primary replica port for this spray group, if specified // @param primary_replica [in] the primary replica port for this spray group, if specified
// @param vchop_map [in] array containing per-port vchop values in column/port format // @param vchop_map [in] array containing per-port vchop values in column/port format
// @param port_list [out] array where the newly built directive list is written // @param port_list [out] array where the newly built directive list is written
@@ -605,330 +422,66 @@ static NvlStatus
_nvswitch_mc_build_portlist _nvswitch_mc_build_portlist
( (
nvswitch_device *device, nvswitch_device *device,
NvU32 *cpb, NvU32 num_ports,
NVSWITCH_COLUMN_PORT_OFFSET_LS10 *ports,
NvU32 primary_replica, NvU32 primary_replica,
NvU8 vchop_map[NVSWITCH_MC_NUM_COLUMNS_LS10][NVSWITCH_MC_PORTS_PER_COLUMN_LS10], NvU8 vchop_map[NVSWITCH_MC_NUM_COLUMNS_LS10][NVSWITCH_MC_PORTS_PER_COLUMN_LS10],
NVSWITCH_TCP_DIRECTIVE_LS10 *port_list, NVSWITCH_TCP_DIRECTIVE_LS10 *port_list,
NvU32 *entries_used NvU32 *entries_used
) )
{ {
NvU32 ecol_idx, ocol_idx, ecol_portcount, ocol_portcount, ecol_portmap, ocol_portmap; NvU8 last_portlist_pos;
NvU32 cur_portlist_pos, j, cur_portlist_slot, last_portlist_pos; NvU8 i;
NvU8 cur_eport, cur_oport, i;
NvS32 extra_ports;
NvU32 port_offsets_by_tcp[NVSWITCH_MC_NUM_COLUMN_PAIRS_LS10][NVSWITCH_MC_PORTS_PER_COLUMN_LS10];
NVSWITCH_TCP_DIRECTIVE_LS10 *cur_dir; NVSWITCH_TCP_DIRECTIVE_LS10 *cur_dir;
if ((cpb == NULL) || (port_list == NULL)) if ((ports == NULL) || (port_list == NULL))
{ {
NVSWITCH_PRINT(device, ERROR, "%s: Invalid arguments\n", __FUNCTION__); NVSWITCH_PRINT(device, ERROR, "%s: Invalid arguments\n", __FUNCTION__);
return -NVL_BAD_ARGS; return -NVL_BAD_ARGS;
} }
_nvswitch_mc_build_mcplist_position_map(port_offsets_by_tcp); // 6.15.2. Route Interface Description
for (i = 0 ; i < num_ports ; ++i)
//
// process columns pairwise. if one column is larger than the other by 2 or more entries,
// set the port as alt path
//
cur_portlist_pos = 0;
last_portlist_pos = 0;
cur_portlist_slot = 0;
for ( i = 0; i < NVSWITCH_MC_NUM_COLUMN_PAIRS_LS10; i++ )
{ {
ecol_idx = 2 * i;
ocol_idx = 2 * i + 1;
ecol_portmap = cpb[ecol_idx]; NvU8 cur_port = ports[i].port_offset;
ocol_portmap = cpb[ocol_idx]; NvU32 cur_col = ports[i].column;
ecol_portcount = _nvswitch_mc_get_pop_count(ecol_portmap); // Populating either EVEN or ODD column but not both
ocol_portcount = _nvswitch_mc_get_pop_count(ocol_portmap); cur_dir = &port_list[i];
cur_dir->primaryReplica = PRIMARY_REPLICA_NONE;
extra_ports = ecol_portcount - ocol_portcount; cur_dir->tcp = cur_col/2; // tile-column pair numbering
if (cur_col % 2 == 1)
// Start current portlist position on column offset of the current column { // odd column port
cur_portlist_slot = 0; cur_dir->tcpOPort = cur_port;
cur_portlist_pos = port_offsets_by_tcp[i][cur_portlist_slot]; cur_dir->tcpEPort = NVSWITCH_MC_NULL_PORT_LS10;
cur_dir->tcpOVCHop = vchop_map[cur_col][cur_port];
if ( extra_ports >= 0 ) if (_is_primary_replica(cur_col, cur_port, primary_replica))
{
//
// even column has more ports or both columns have an equal number
// iterate on odd column port count to go through both columns
//
for (j = 0; j < ocol_portcount; j++, cur_portlist_slot++)
{ {
cur_eport = _nvswitch_mc_get_next_port(&ecol_portmap); cur_dir->primaryReplica = PRIMARY_REPLICA_ODD;
cur_oport = _nvswitch_mc_get_next_port(&ocol_portmap);
if ((cur_eport == NVSWITCH_MC_NULL_PORT_LS10) ||
(cur_oport == NVSWITCH_MC_NULL_PORT_LS10))
{
return -NVL_ERR_GENERIC;
}
// assign the ports to the current directive #ifdef NVSWITCH_MC_DEBUG
cur_portlist_pos = port_offsets_by_tcp[i][cur_portlist_slot]; NVSWITCH_PRINT(device, DEBUG, "%s: Odd column primary replica programmed: %d %d\n",
cur_dir = &port_list[cur_portlist_pos]; __FUNCTION__, primary_replica, i);
cur_dir->tcpEPort = cur_eport;
cur_dir->tcpOPort = cur_oport;
cur_dir->tcpEVCHop = vchop_map[ecol_idx][cur_eport];
cur_dir->tcpOVCHop = vchop_map[ocol_idx][cur_oport];
cur_dir->tcp = i;
#ifdef NVSWITCH_MC_TRACE
NVSWITCH_PRINT(device, INFO, "%s: tcp: %d, extra: %d, cur_eport: %d, cur_oport %d\n",
__FUNCTION__, i, extra_ports, cur_eport, cur_oport);
NVSWITCH_PRINT(device, INFO, "%s: cur_portlist_pos: %d\n", __FUNCTION__,
cur_portlist_pos);
#endif #endif
// set primary replica
if (_is_primary_replica(ocol_idx, cur_oport, primary_replica))
cur_dir->primaryReplica = PRIMARY_REPLICA_ODD;
if (_is_primary_replica(ecol_idx, cur_eport, primary_replica))
cur_dir->primaryReplica = PRIMARY_REPLICA_EVEN;
}
// if both columns had the same number of ports, move on to the next column pair
if (!extra_ports)
{
last_portlist_pos = NV_MAX(last_portlist_pos, cur_portlist_pos);
continue;
}
//
// otherwise, handle remaining ports in even column
// for the first extra port, assign it directly
// cur_portlist_slot is incremented by the last iteration, or 0
//
cur_eport = _nvswitch_mc_get_next_port(&ecol_portmap);
if (cur_eport == NVSWITCH_MC_NULL_PORT_LS10)
{
return -NVL_ERR_GENERIC;
}
cur_portlist_pos = port_offsets_by_tcp[i][cur_portlist_slot];
cur_dir = &port_list[cur_portlist_pos];
cur_dir->tcpEPort = cur_eport;
cur_dir->tcpEVCHop = vchop_map[ecol_idx][cur_eport];
cur_dir->tcp = i;
#ifdef NVSWITCH_MC_TRACE
NVSWITCH_PRINT(device, INFO, "%s: tcp: %d, extra: %d, cur_eport: %d\n",
__FUNCTION__, i, extra_ports, cur_eport);
NVSWITCH_PRINT(device, INFO, "%s: cur_portlist_pos: %d\n", __FUNCTION__,
cur_portlist_pos);
#endif
// if this is the primary replica port, mark it
if (_is_primary_replica(ecol_idx, cur_eport, primary_replica))
cur_dir->primaryReplica = PRIMARY_REPLICA_EVEN;
extra_ports--;
// if there are more, assign to altpath
while (extra_ports)
{
// get next port from even column
cur_eport = _nvswitch_mc_get_next_port(&ecol_portmap);
if (cur_eport == NVSWITCH_MC_NULL_PORT_LS10)
{
return -NVL_ERR_GENERIC;
}
// assign it to odd port in current directive (altpath)
cur_dir->tcpOPort = cur_eport;
cur_dir->tcpOAltPath = NV_TRUE;
cur_dir->tcpOVCHop = vchop_map[ecol_idx][cur_eport];
#ifdef NVSWITCH_MC_TRACE
NVSWITCH_PRINT(device, INFO, "%s: tcp: %d, extra: %d, cur_eport: %d (alt)\n",
__FUNCTION__, i, extra_ports, cur_eport);
NVSWITCH_PRINT(device, INFO, "%s: cur_portlist_pos: %d\n", __FUNCTION__,
cur_portlist_pos);
#endif
// if this is the primary replica port, mark _ODD due to altpath
if (_is_primary_replica(ecol_idx, cur_eport, primary_replica))
cur_dir->primaryReplica = PRIMARY_REPLICA_ODD;
extra_ports--;
// if there are more ports remaining, start the next entry
if (extra_ports)
{
// advance the portlist entry
cur_portlist_slot++;
cur_portlist_pos = port_offsets_by_tcp[i][cur_portlist_slot];
cur_dir = &port_list[cur_portlist_pos];
cur_eport = _nvswitch_mc_get_next_port(&ecol_portmap);
if (cur_eport == NVSWITCH_MC_NULL_PORT_LS10)
{
return -NVL_ERR_GENERIC;
}
cur_dir->tcpEPort = cur_eport;
cur_dir->tcpEVCHop = vchop_map[ecol_idx][cur_eport];
cur_dir->tcp = i;
#ifdef NVSWITCH_MC_TRACE
NVSWITCH_PRINT(device, INFO, "%s: tcp: %d, extra: %d, cur_eport: %d\n",
__FUNCTION__, i, extra_ports, cur_eport);
NVSWITCH_PRINT(device, INFO, "%s: cur_portlist_pos: %d\n", __FUNCTION__,
cur_portlist_pos);
#endif
// if this is the primary replica port, mark it
if (_is_primary_replica(ecol_idx, cur_eport, primary_replica))
cur_dir->primaryReplica = PRIMARY_REPLICA_EVEN;
extra_ports--;
}
} }
} }
else else
{ { // even column port
// odd column has more ports cur_dir->tcpEPort = cur_port;
extra_ports = -extra_ports; cur_dir->tcpOPort = NVSWITCH_MC_NULL_PORT_LS10;
cur_dir->tcpEVCHop = vchop_map[cur_col][cur_port];
// iterate over even column to go through port pairs if (_is_primary_replica(cur_col, cur_port, primary_replica))
for (j = 0; j < ecol_portcount; j++, cur_portlist_slot++)
{ {
cur_eport = _nvswitch_mc_get_next_port(&ecol_portmap); cur_dir->primaryReplica = PRIMARY_REPLICA_EVEN;
cur_oport = _nvswitch_mc_get_next_port(&ocol_portmap); #ifdef NVSWITCH_MC_DEBUG
if ((cur_eport == NVSWITCH_MC_NULL_PORT_LS10) || NVSWITCH_PRINT(device, DEBUG, "%s: Even column primary replica programmed: %d %d\n",
(cur_oport == NVSWITCH_MC_NULL_PORT_LS10)) __FUNCTION__, primary_replica, i);
{
return -NVL_ERR_GENERIC;
}
// assign the ports to the current directive
cur_portlist_pos = port_offsets_by_tcp[i][cur_portlist_slot];
cur_dir = &port_list[cur_portlist_pos];
cur_dir->tcpEPort = cur_eport;
cur_dir->tcpOPort = cur_oport;
cur_dir->tcpEVCHop = vchop_map[ecol_idx][cur_eport];
cur_dir->tcpOVCHop = vchop_map[ocol_idx][cur_oport];
cur_dir->tcp = i;
#ifdef NVSWITCH_MC_TRACE
NVSWITCH_PRINT(device, INFO, "%s: tcp: %d, extra: %d, cur_eport: %d, cur_oport %d\n",
__FUNCTION__, i, extra_ports, cur_eport, cur_oport);
NVSWITCH_PRINT(device, INFO, "%s: cur_portlist_pos: %d\n", __FUNCTION__,
cur_portlist_pos);
#endif #endif
if (_is_primary_replica(ocol_idx, cur_oport, primary_replica))
cur_dir->primaryReplica = PRIMARY_REPLICA_ODD;
if (_is_primary_replica(ecol_idx, cur_eport, primary_replica))
cur_dir->primaryReplica = PRIMARY_REPLICA_EVEN;
}
// handle the leftover ports in odd column
cur_oport = _nvswitch_mc_get_next_port(&ocol_portmap);
if (cur_oport == NVSWITCH_MC_NULL_PORT_LS10)
{
return -NVL_ERR_GENERIC;
}
// cur_portlist_slot is incremented by the last iteration, or 0
cur_portlist_pos = port_offsets_by_tcp[i][cur_portlist_slot];
cur_dir = &port_list[cur_portlist_pos];
cur_dir->tcpOPort = cur_oport;
cur_dir->tcpOVCHop = vchop_map[ocol_idx][cur_oport];
cur_dir->tcp = i;
#ifdef NVSWITCH_MC_TRACE
NVSWITCH_PRINT(device, INFO, "%s: tcp: %d, extra: %d, cur_oport %d\n",
__FUNCTION__, i, extra_ports, cur_oport);
NVSWITCH_PRINT(device, INFO, "%s: cur_portlist_pos: %d\n", __FUNCTION__,
cur_portlist_pos);
#endif
if (_is_primary_replica(ocol_idx, cur_oport, primary_replica))
cur_dir->primaryReplica = PRIMARY_REPLICA_ODD;
extra_ports--;
// process any remaining ports in odd column
while (extra_ports)
{
// get next odd port
cur_oport = _nvswitch_mc_get_next_port(&ocol_portmap);
if (cur_oport == NVSWITCH_MC_NULL_PORT_LS10)
{
return -NVL_ERR_GENERIC;
}
// set it as even altpath port in current directive
cur_dir->tcpEPort = cur_oport;
cur_dir->tcpEAltPath = NV_TRUE;
cur_dir->tcpEVCHop = vchop_map[ocol_idx][cur_oport];
#ifdef NVSWITCH_MC_TRACE
NVSWITCH_PRINT(device, INFO, "%s: tcp: %d, extra: %d, cur_oport %d (alt)\n",
__FUNCTION__, i, extra_ports, cur_oport);
NVSWITCH_PRINT(device, INFO, "%s: cur_portlist_pos: %d\n", __FUNCTION__,
cur_portlist_pos);
#endif
// if this is the primary replica port, mark _EVEN due to altpath
if (_is_primary_replica(ocol_idx, cur_oport, primary_replica))
cur_dir->primaryReplica = PRIMARY_REPLICA_EVEN;
extra_ports--;
// if there is another port, it goes in the next directive
if (extra_ports)
{
cur_portlist_slot++;
cur_portlist_pos = port_offsets_by_tcp[i][cur_portlist_slot];
cur_dir = &port_list[cur_portlist_pos];
cur_oport = _nvswitch_mc_get_next_port(&ocol_portmap);
if (cur_oport == NVSWITCH_MC_NULL_PORT_LS10)
{
return -NVL_ERR_GENERIC;
}
cur_dir->tcpOPort = cur_oport;
cur_dir->tcpOVCHop = vchop_map[ocol_idx][cur_oport];
cur_dir->tcp = i;
#ifdef NVSWITCH_MC_TRACE
NVSWITCH_PRINT(device, INFO, "%s: tcp: %d, extra: %d, cur_oport %d\n",
__FUNCTION__, i, extra_ports, cur_oport);
NVSWITCH_PRINT(device, INFO, "%s: cur_portlist_pos: %d\n", __FUNCTION__,
cur_portlist_pos);
#endif
if (_is_primary_replica(ocol_idx, cur_oport, primary_replica))
cur_dir->primaryReplica = PRIMARY_REPLICA_ODD;
extra_ports--;
}
} }
} }
last_portlist_pos = NV_MAX(last_portlist_pos, cur_portlist_pos); last_portlist_pos = i;
} }
// set the lastRound flag for the last entry in the spray string // set the lastRound flag for the last entry in the spray string
@@ -939,8 +492,8 @@ _nvswitch_mc_build_portlist
#ifdef NVSWITCH_MC_DEBUG #ifdef NVSWITCH_MC_DEBUG
NVSWITCH_PRINT(device, INFO, NVSWITCH_PRINT(device, INFO,
"%s: entries_used: %d, cur_portlist_pos: %d last_portlist_pos: %d\n", "%s: entries_used: %d, last_portlist_pos: %d\n",
__FUNCTION__, *entries_used, cur_portlist_pos, last_portlist_pos); __FUNCTION__, *entries_used, last_portlist_pos);
#endif #endif
return NVL_SUCCESS; return NVL_SUCCESS;
@@ -1068,7 +621,7 @@ nvswitch_mc_build_mcp_list_ls10
NvU32 dir_entries_used_sg = 0; NvU32 dir_entries_used_sg = 0;
NvU32 dir_entries_used = 0; NvU32 dir_entries_used = 0;
NvU32 mcplist_offset = 0; NvU32 mcplist_offset = 0;
NvU32 cpb[NVSWITCH_MC_NUM_COLUMNS_LS10] = { 0 }; NVSWITCH_COLUMN_PORT_OFFSET_LS10 ports[NVSWITCH_NUM_LINKS_LS10];
NvU8 vchop_map[NVSWITCH_MC_NUM_COLUMNS_LS10][NVSWITCH_MC_PORTS_PER_COLUMN_LS10]; NvU8 vchop_map[NVSWITCH_MC_NUM_COLUMNS_LS10][NVSWITCH_MC_PORTS_PER_COLUMN_LS10];
NVSWITCH_TCP_DIRECTIVE_LS10 tmp_mcp_list[NVSWITCH_MC_TCP_LIST_SIZE_LS10]; NVSWITCH_TCP_DIRECTIVE_LS10 tmp_mcp_list[NVSWITCH_MC_TCP_LIST_SIZE_LS10];
NVSWITCH_TCP_DIRECTIVE_LS10 *mcp_list; NVSWITCH_TCP_DIRECTIVE_LS10 *mcp_list;
@@ -1108,7 +661,7 @@ nvswitch_mc_build_mcp_list_ls10
return -NVL_BAD_ARGS; return -NVL_BAD_ARGS;
} }
if (ports_per_spray_group[i] > NVSWITCH_NUM_LINKS_LS10) if (ports_per_spray_group[i] > NVSWITCH_MC_TCP_LIST_SIZE_LS10)
{ {
NVSWITCH_PRINT(device, ERROR, "%s: Too many ports in spray group %d\n", NVSWITCH_PRINT(device, ERROR, "%s: Too many ports in spray group %d\n",
__FUNCTION__, i); __FUNCTION__, i);
@@ -1118,7 +671,7 @@ nvswitch_mc_build_mcp_list_ls10
j += ports_per_spray_group[i]; j += ports_per_spray_group[i];
} }
if (j > NVSWITCH_NUM_LINKS_LS10) if (j > NVSWITCH_MC_TCP_LIST_SIZE_LS10)
{ {
NVSWITCH_PRINT(device, ERROR, "%s: Too many ports specified in total spray groups: %d\n", NVSWITCH_PRINT(device, ERROR, "%s: Too many ports specified in total spray groups: %d\n",
__FUNCTION__, j); __FUNCTION__, j);
@@ -1143,14 +696,13 @@ nvswitch_mc_build_mcp_list_ls10
if (ret != NVL_SUCCESS) if (ret != NVL_SUCCESS)
return ret; return ret;
ret = _nvswitch_mc_build_cpb(device, spray_group_size, &port_list[spray_group_offset], ret = _nvswitch_mc_build_ports_array(device, spray_group_size, &port_list[spray_group_offset],
NVSWITCH_MC_NUM_COLUMNS_LS10, cpb, ports, &vchop_array[spray_group_offset], vchop_map);
&vchop_array[spray_group_offset], vchop_map);
if (ret != NVL_SUCCESS) if (ret != NVL_SUCCESS)
{ {
NVSWITCH_PRINT(device, ERROR, NVSWITCH_PRINT(device, ERROR,
"%s: error building column-port bitmap for spray group %d: %d\n", "%s: error building port-column array for spray group %d: %d\n",
__FUNCTION__, spray_group_idx, ret); __FUNCTION__, spray_group_idx, ret);
return ret; return ret;
} }
@@ -1158,25 +710,6 @@ nvswitch_mc_build_mcp_list_ls10
// Set the offset to this spray group in the mcp list. // Set the offset to this spray group in the mcp list.
spray_group_ptrs[spray_group_idx] = (NvU8)dir_entries_used; spray_group_ptrs[spray_group_idx] = (NvU8)dir_entries_used;
#ifdef NVSWITCH_MC_TRACE
NVSWITCH_PRINT(device, INFO, "%s: spray group offset for group %d is %d\n",
__FUNCTION__, spray_group_idx, dir_entries_used);
for (i = 0; i < NVSWITCH_MC_NUM_COLUMNS_LS10; i++)
{
NVSWITCH_PRINT(device, INFO, "%d Relative ports in column %d\n",
_nvswitch_mc_get_pop_count(cpb[i]), i);
for ( j = 0; j < 32; j++ )
{
if (nvswitch_test_flags(cpb[i], NVBIT(j)))
{
NVSWITCH_PRINT(device, INFO, "%4d", j);
}
}
NVSWITCH_PRINT(device, INFO, "\n");
}
#endif
// if primary replica is specified for this spray group, find the port number // if primary replica is specified for this spray group, find the port number
if (replica_valid_array[spray_group_idx]) if (replica_valid_array[spray_group_idx])
{ {
@@ -1220,8 +753,7 @@ nvswitch_mc_build_mcp_list_ls10
NVSWITCH_PRINT(device, INFO, "%s: building tmp mc portlist at mcp offset %d, size %d\n", NVSWITCH_PRINT(device, INFO, "%s: building tmp mc portlist at mcp offset %d, size %d\n",
__FUNCTION__, mcplist_offset, spray_group_size); __FUNCTION__, mcplist_offset, spray_group_size);
#endif #endif
ret = _nvswitch_mc_build_portlist(device, spray_group_size, ports, primary_replica_port, vchop_map,
ret = _nvswitch_mc_build_portlist(device, cpb, primary_replica_port, vchop_map,
tmp_mcp_list, &dir_entries_used_sg); tmp_mcp_list, &dir_entries_used_sg);
if (ret != NVL_SUCCESS) if (ret != NVL_SUCCESS)
@@ -1234,14 +766,6 @@ nvswitch_mc_build_mcp_list_ls10
NVSWITCH_PRINT(device, INFO, "%s: entries used after building portlist: %d\n", NVSWITCH_PRINT(device, INFO, "%s: entries used after building portlist: %d\n",
__FUNCTION__, dir_entries_used_sg); __FUNCTION__, dir_entries_used_sg);
#endif #endif
ret = _nvswitch_mc_compact_portlist(device, tmp_mcp_list, &dir_entries_used_sg);
if (ret != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR, "%s: error compacting MC portlist\n", __FUNCTION__);
return ret;
}
_nvswitch_mc_set_round_flags(tmp_mcp_list, dir_entries_used_sg); _nvswitch_mc_set_round_flags(tmp_mcp_list, dir_entries_used_sg);
_nvswitch_mc_set_port_flags(tmp_mcp_list, dir_entries_used_sg); _nvswitch_mc_set_port_flags(tmp_mcp_list, dir_entries_used_sg);
@@ -1306,7 +830,7 @@ nvswitch_mc_unwind_directives_ls10
{ {
NvU32 ret = NVL_SUCCESS; NvU32 ret = NVL_SUCCESS;
NvU32 i, port_idx, cur_sg, ports_in_cur_sg, port, primary_replica; NvU32 i, port_idx, cur_sg, ports_in_cur_sg, port, primary_replica;
NVSWITCH_TCP_DIRECTIVE_LS10 cur_dir, prev_dir; NVSWITCH_TCP_DIRECTIVE_LS10 cur_dir;
cur_sg = 0; cur_sg = 0;
port_idx = 0; port_idx = 0;
@@ -1344,33 +868,30 @@ nvswitch_mc_unwind_directives_ls10
} }
// //
// If the previous TCP directive's portFlag = 0, and if it was not // If directive's portFlag == 1, this TCP directive contains the
// used to select the even or odd port of its predecessor, and this
// directive's portFlag == 1, this TCP directive contains the
// primary replica, and the next TCP directive's portFlag = 0/1 // primary replica, and the next TCP directive's portFlag = 0/1
// selects the even/odd port of this TCP directive. // selects the even/odd port of this TCP directive.
// //
else if ((i < (NVSWITCH_MC_TCP_LIST_SIZE_LS10 - 1)) && (cur_dir.portFlag == 1))
// If we don't have the first or last directive and portFlag == 1
else if ((i < (NVSWITCH_MC_TCP_LIST_SIZE_LS10 - 1)) && (i > 0) && (cur_dir.portFlag == 1))
{ {
prev_dir = directives[i - 1]; // The next directive's portFlags specify even or odd
if (directives[i + 1].portFlag)
// Is the previous directive in the same sg and is the portFlag == 0? primary_replica = PRIMARY_REPLICA_ODD;
if ((prev_dir.lastRound == 0) && (prev_dir.portFlag == 0)) else
{ primary_replica = PRIMARY_REPLICA_EVEN;
// Check if there is no predecessor, or if the predecessor's portFlag == 0
if ((i < 2) || (directives[i - 2].portFlag == 0))
{
// The next directive's portFlags specify even or odd
if (directives[i + 1].portFlag)
primary_replica = PRIMARY_REPLICA_ODD;
else
primary_replica = PRIMARY_REPLICA_EVEN;
}
}
} }
#ifdef NVSWITCH_MC_TRACE
if (primary_replica == PRIMARY_REPLICA_ODD) {
NVSWITCH_PRINT(device, INFO, "%s: Odd primary replica detected: %d\n",
__FUNCTION__, i);
}
if (primary_replica == PRIMARY_REPLICA_EVEN) {
NVSWITCH_PRINT(device, INFO, "%s: Even primary replica detected: %d\n",
__FUNCTION__, i);
}
#endif
if (cur_dir.tcpEPort != NVSWITCH_MC_NULL_PORT_LS10) if (cur_dir.tcpEPort != NVSWITCH_MC_NULL_PORT_LS10)
{ {
ports_in_cur_sg++; ports_in_cur_sg++;
@@ -1510,6 +1031,13 @@ nvswitch_mc_invalidate_mc_rid_entry_ls10
return -NVL_BAD_ARGS; return -NVL_BAD_ARGS;
} }
if (nvswitch_is_tnvl_mode_locked(device))
{
NVSWITCH_PRINT(device, ERROR,
"%s(%d): Security locked\n", __FUNCTION__, __LINE__);
return -NVL_ERR_INSUFFICIENT_PERMISSIONS;
}
if (use_extended_table) if (use_extended_table)
reg = FLD_SET_DRF(_ROUTE, _RIDTABADDR, _RAM_SEL, _SELECTSEXTMCRIDROUTERAM, 0); reg = FLD_SET_DRF(_ROUTE, _RIDTABADDR, _RAM_SEL, _SELECTSEXTMCRIDROUTERAM, 0);
else else
@@ -1608,6 +1136,13 @@ nvswitch_mc_program_mc_rid_entry_ls10
return -NVL_BAD_ARGS; return -NVL_BAD_ARGS;
} }
if (nvswitch_is_tnvl_mode_locked(device))
{
NVSWITCH_PRINT(device, ERROR,
"%s(%d): Security locked\n", __FUNCTION__, __LINE__);
return -NVL_ERR_INSUFFICIENT_PERMISSIONS;
}
if (table_entry->use_extended_table) if (table_entry->use_extended_table)
reg = FLD_SET_DRF(_ROUTE, _RIDTABADDR, _RAM_SEL, _SELECTSEXTMCRIDROUTERAM, 0); reg = FLD_SET_DRF(_ROUTE, _RIDTABADDR, _RAM_SEL, _SELECTSEXTMCRIDROUTERAM, 0);
else else
@@ -1749,6 +1284,13 @@ nvswitch_mc_read_mc_rid_entry_ls10
return -NVL_BAD_ARGS; return -NVL_BAD_ARGS;
} }
if (nvswitch_is_tnvl_mode_locked(device))
{
NVSWITCH_PRINT(device, ERROR,
"%s(%d): Security locked\n", __FUNCTION__, __LINE__);
return -NVL_ERR_INSUFFICIENT_PERMISSIONS;
}
// set the address // set the address
if (table_entry->use_extended_table) if (table_entry->use_extended_table)
reg = FLD_SET_DRF(_ROUTE, _RIDTABADDR, _RAM_SEL, _SELECTSEXTMCRIDROUTERAM, 0); reg = FLD_SET_DRF(_ROUTE, _RIDTABADDR, _RAM_SEL, _SELECTSEXTMCRIDROUTERAM, 0);
@@ -1841,4 +1383,3 @@ nvswitch_mc_read_mc_rid_entry_ls10
return NVL_SUCCESS; return NVL_SUCCESS;
} }

View File

@@ -538,7 +538,11 @@ static void __nvoc_init_funcTable_KernelBif_1(KernelBif *pThis, RmHalspecOwner *
} }
// Hal function -- kbifInitXveRegMap // Hal function -- kbifInitXveRegMap
if (( ((chipHal_HalVarIdx >> 5) == 1UL) && ((1UL << (chipHal_HalVarIdx & 0x1f)) & 0x000003e0UL) )) /* ChipHal: TU102 | TU104 | TU106 | TU116 | TU117 */ if (( ((chipHal_HalVarIdx >> 5) == 1UL) && ((1UL << (chipHal_HalVarIdx & 0x1f)) & 0x00000400UL) )) /* ChipHal: GA100 */
{
pThis->__kbifInitXveRegMap__ = &kbifInitXveRegMap_GA100;
}
else if (( ((chipHal_HalVarIdx >> 5) == 1UL) && ((1UL << (chipHal_HalVarIdx & 0x1f)) & 0x000003e0UL) )) /* ChipHal: TU102 | TU104 | TU106 | TU116 | TU117 */
{ {
pThis->__kbifInitXveRegMap__ = &kbifInitXveRegMap_TU102; pThis->__kbifInitXveRegMap__ = &kbifInitXveRegMap_TU102;
} }

View File

@@ -790,6 +790,8 @@ static inline NV_STATUS kbifDoFunctionLevelReset_DISPATCH(struct OBJGPU *pGpu, s
NV_STATUS kbifInitXveRegMap_TU102(struct OBJGPU *pGpu, struct KernelBif *pKernelBif, NvU8 arg0); NV_STATUS kbifInitXveRegMap_TU102(struct OBJGPU *pGpu, struct KernelBif *pKernelBif, NvU8 arg0);
NV_STATUS kbifInitXveRegMap_GA100(struct OBJGPU *pGpu, struct KernelBif *pKernelBif, NvU8 arg0);
NV_STATUS kbifInitXveRegMap_GA102(struct OBJGPU *pGpu, struct KernelBif *pKernelBif, NvU8 arg0); NV_STATUS kbifInitXveRegMap_GA102(struct OBJGPU *pGpu, struct KernelBif *pKernelBif, NvU8 arg0);
static inline NV_STATUS kbifInitXveRegMap_DISPATCH(struct OBJGPU *pGpu, struct KernelBif *pKernelBif, NvU8 arg0) { static inline NV_STATUS kbifInitXveRegMap_DISPATCH(struct OBJGPU *pGpu, struct KernelBif *pKernelBif, NvU8 arg0) {

View File

@@ -28,9 +28,67 @@
#include "published/ampere/ga100/dev_nv_xve_addendum.h" #include "published/ampere/ga100/dev_nv_xve_addendum.h"
#include "published/ampere/ga100/dev_nv_xve.h" #include "published/ampere/ga100/dev_nv_xve.h"
#include "published/ampere/ga100/dev_boot.h" #include "published/ampere/ga100/dev_boot.h"
#include "published/ampere/ga100/dev_nv_pcfg_xve_regmap.h"
#include "nvmisc.h"
/* ------------------------ Public Functions -------------------------------- */ /* ------------------------ Public Functions -------------------------------- */
// XVE register map for PCIe config space
static const NvU32 xveRegMapValid[] = NV_PCFG_XVE_REGISTER_VALID_MAP;
static const NvU32 xveRegMapWrite[] = NV_PCFG_XVE_REGISTER_WR_MAP;
/* ------------------------ Public Functions -------------------------------- */
/*!
* This function setups the xve register map pointers
*
* @param[in] pGpu GPU object pointer
* @param[in] pKernelBif Pointer to KernelBif object
* @param[in] func PCIe function number
*
* @return 'NV_OK' if successful, an RM error code otherwise.
*/
NV_STATUS
kbifInitXveRegMap_GA100
(
OBJGPU *pGpu,
KernelBif *pKernelBif,
NvU8 func
)
{
extern NvU32 kbifInitXveRegMap_GM107(OBJGPU *pGpu, KernelBif *pKernelBif, NvU8 func);
NV_STATUS status = NV_OK;
NvU32 controlSize = 0;
if (func == 0)
{
pKernelBif->xveRegmapRef[0].nFunc = 0;
pKernelBif->xveRegmapRef[0].xveRegMapValid = xveRegMapValid;
pKernelBif->xveRegmapRef[0].xveRegMapWrite = xveRegMapWrite;
pKernelBif->xveRegmapRef[0].numXveRegMapValid = NV_ARRAY_ELEMENTS(xveRegMapValid);
pKernelBif->xveRegmapRef[0].numXveRegMapWrite = NV_ARRAY_ELEMENTS(xveRegMapWrite);
pKernelBif->xveRegmapRef[0].bufBootConfigSpace = pKernelBif->cacheData.gpuBootConfigSpace;
// Each MSIX table entry is 4 NvU32s
controlSize = kbifGetMSIXTableVectorControlSize_HAL(pGpu, pKernelBif);
if (pKernelBif->xveRegmapRef[0].bufMsixTable == NULL)
pKernelBif->xveRegmapRef[0].bufMsixTable = portMemAllocNonPaged(controlSize * 4 * sizeof(NvU32));
NV_ASSERT_OR_RETURN(pKernelBif->xveRegmapRef[0].bufMsixTable != NULL, NV_ERR_NO_MEMORY);
}
else if (func == 1)
{
// Init regmap for Fn1 using older HAL
status = kbifInitXveRegMap_GM107(pGpu, pKernelBif, 1);
}
else
{
NV_PRINTF(LEVEL_ERROR, "Invalid argument, func: %d.\n", func);
NV_ASSERT(0);
status = NV_ERR_INVALID_ARGUMENT;
}
return status;
}
/*! /*!
* @brief Apply WAR for bug 3208922 - disable P2P on Ampere NB * @brief Apply WAR for bug 3208922 - disable P2P on Ampere NB
* *

View File

@@ -941,13 +941,26 @@ kfifoChidMgrReleaseChid_IMPL
if (IS_GFID_VF(gfid)) if (IS_GFID_VF(gfid))
{ {
NV_ASSERT_OR_RETURN(pChidMgr->ppVirtualChIDHeap[gfid] != NULL, NV_ERR_INVALID_STATE); //
NV_ASSERT_OK(pChidMgr->ppVirtualChIDHeap[gfid]->eheapFree(pChidMgr->ppVirtualChIDHeap[gfid], ChID)); // ppVirtualChIDHeap is freed during hostvgpudeviceapiDestruct in GSP-RM.
// In the case of a GSP-Plugin crash after running the VF doorbell fuzzer, only the hostvgpudeviceapi object is freed in GSP-RM.
// Other resources are cleaned up when shutting down the VM.
//
if (pChidMgr->ppVirtualChIDHeap[gfid] != NULL)
{
NV_ASSERT_OK(pChidMgr->ppVirtualChIDHeap[gfid]->eheapFree(pChidMgr->ppVirtualChIDHeap[gfid], ChID));
}
} }
else else
{ {
NV_ASSERT_OR_RETURN(pChidMgr->pGlobalChIDHeap != NULL, NV_ERR_INVALID_STATE); if (pChidMgr->pGlobalChIDHeap != NULL)
NV_ASSERT_OK(pChidMgr->pGlobalChIDHeap->eheapFree(pChidMgr->pGlobalChIDHeap, ChID)); {
NV_ASSERT_OK(pChidMgr->pGlobalChIDHeap->eheapFree(pChidMgr->pGlobalChIDHeap, ChID));
}
else
{
NV_ASSERT(pChidMgr->pGlobalChIDHeap != NULL);
}
} }
NV_ASSERT_OR_RETURN(pChidMgr->pFifoDataHeap != NULL, NV_ERR_INVALID_STATE); NV_ASSERT_OR_RETURN(pChidMgr->pFifoDataHeap != NULL, NV_ERR_INVALID_STATE);
@@ -2691,7 +2704,7 @@ kfifoRunlistAllocBuffers_IMPL
} }
} }
memdescTagAlloc(status, NV_FB_ALLOC_RM_INTERNAL_OWNER_UNNAMED_TAG_101, memdescTagAlloc(status, NV_FB_ALLOC_RM_INTERNAL_OWNER_UNNAMED_TAG_101,
ppMemDesc[counter]); ppMemDesc[counter]);
if (status != NV_OK) if (status != NV_OK)
{ {

View File

@@ -76,18 +76,34 @@ portStringCompare
NvLength maxLength NvLength maxLength
) )
{ {
NvLength length; NvLength i;
PORT_ASSERT_CHECKED(str1 != NULL); PORT_ASSERT_CHECKED(str1 != NULL);
PORT_ASSERT_CHECKED(str2 != NULL); PORT_ASSERT_CHECKED(str2 != NULL);
length = portStringLengthSafe(str1, maxLength); for (i = 0; i < maxLength; i++)
{
if (str1[i] != str2[i])
{
//
// Cast to unsigned before assigning to NvS32, to avoid sign
// extension. E.g., if str1[i] is 0xff, we want s1 to contain
// 0xff, not -1. In practice, this shouldn't matter for printable
// characters, but still...
//
NvS32 s1 = (unsigned char)str1[i];
NvS32 s2 = (unsigned char)str2[i];
return s1 - s2;
}
// Add 1 for the null terminator. if ((str1[i] == '\0') &&
if (length < maxLength) (str2[i] == '\0'))
length++; {
break;
}
}
return portMemCmp(str1, str2, length); return 0;
} }
#endif #endif

View File

@@ -1,4 +1,4 @@
NVIDIA_VERSION = 550.142 NVIDIA_VERSION = 550.144.03
# This file. # This file.
VERSION_MK_FILE := $(lastword $(MAKEFILE_LIST)) VERSION_MK_FILE := $(lastword $(MAKEFILE_LIST))