515.48.07

This commit is contained in:
Andy Ritger
2022-05-27 16:40:24 -07:00
parent af26e1ea89
commit 965db98552
114 changed files with 18493 additions and 22785 deletions

View File

@@ -72,7 +72,7 @@ EXTRA_CFLAGS += -I$(src)/common/inc
EXTRA_CFLAGS += -I$(src)
EXTRA_CFLAGS += -Wall -MD $(DEFINES) $(INCLUDES) -Wno-cast-qual -Wno-error -Wno-format-extra-args
EXTRA_CFLAGS += -D__KERNEL__ -DMODULE -DNVRM
EXTRA_CFLAGS += -DNV_VERSION_STRING=\"515.43.04\"
EXTRA_CFLAGS += -DNV_VERSION_STRING=\"515.48.07\"
EXTRA_CFLAGS += -Wno-unused-function
@@ -94,6 +94,7 @@ EXTRA_CFLAGS += -ffreestanding
ifeq ($(ARCH),arm64)
EXTRA_CFLAGS += -mgeneral-regs-only -march=armv8-a
EXTRA_CFLAGS += $(call cc-option,-mno-outline-atomics,)
endif
ifeq ($(ARCH),x86_64)

View File

@@ -1647,23 +1647,12 @@ extern NvBool nv_ats_supported;
* and any other baggage we want to carry along
*
*/
#define NV_MAXNUM_DISPLAY_DEVICES 8
typedef struct
{
acpi_handle dev_handle;
int dev_id;
} nv_video_t;
typedef struct
{
nvidia_stack_t *sp;
struct acpi_device *device;
nv_video_t pNvVideo[NV_MAXNUM_DISPLAY_DEVICES];
struct acpi_handle *handle;
int notify_handler_installed;
int default_display_mask;
} nv_acpi_t;
#endif

View File

@@ -35,8 +35,6 @@ extern nvidia_module_t nv_fops;
void nv_acpi_register_notifier (nv_linux_state_t *);
void nv_acpi_unregister_notifier (nv_linux_state_t *);
int nv_acpi_init (void);
int nv_acpi_uninit (void);
NvU8 nv_find_pci_capability (struct pci_dev *, NvU8);

View File

@@ -576,11 +576,9 @@ typedef enum
((nv)->iso_iommu_present)
/*
* NVIDIA ACPI event IDs to be passed into the core NVIDIA
* driver for various events like display switch events,
* AC/battery events, etc..
* NVIDIA ACPI event ID to be passed into the core NVIDIA driver for
* AC/DC event.
*/
#define NV_SYSTEM_ACPI_DISPLAY_SWITCH_EVENT 0x8001
#define NV_SYSTEM_ACPI_BATTERY_POWER_EVENT 0x8002
/*
@@ -589,14 +587,6 @@ typedef enum
#define NV_SYSTEM_GPU_ADD_EVENT 0x9001
#define NV_SYSTEM_GPU_REMOVE_EVENT 0x9002
/*
* Status bit definitions for display switch hotkey events.
*/
#define NV_HOTKEY_STATUS_DISPLAY_ENABLE_LCD 0x01
#define NV_HOTKEY_STATUS_DISPLAY_ENABLE_CRT 0x02
#define NV_HOTKEY_STATUS_DISPLAY_ENABLE_TV 0x04
#define NV_HOTKEY_STATUS_DISPLAY_ENABLE_DFP 0x08
/*
* NVIDIA ACPI sub-event IDs (event types) to be passed into
* to core NVIDIA driver for ACPI events.

View File

@@ -1120,6 +1120,23 @@ compile_test() {
compile_check_conftest "$CODE" "NV_MDEV_SET_IOMMU_DEVICE_PRESENT" "" "functions"
;;
mdev_parent_ops_has_open_device)
# Determine if 'mdev_parent_ops' structure has a 'open_device'
# field.
#
# Added by commit 2fd585f4ed9d ("vfio: Provide better generic support
# for open/release vfio_device_ops") in 5.15 (2021-08-05)
#
CODE="
#include <linux/pci.h>
#include <linux/mdev.h>
int conftest_mdev_parent_ops_has_open_device(void) {
return offsetof(struct mdev_parent_ops, open_device);
}"
compile_check_conftest "$CODE" "NV_MDEV_PARENT_OPS_HAS_OPEN_DEVICE" "" "types"
;;
pci_irq_vector_helpers)
#
# Determine if pci_alloc_irq_vectors(), pci_free_irq_vectors()
@@ -1154,23 +1171,6 @@ compile_test() {
compile_check_conftest "$CODE" "NV_VFIO_DEVICE_GFX_PLANE_INFO_PRESENT" "" "types"
;;
vfio_device_migration_info)
#
# determine if the 'struct vfio_device_migration_info' type is present.
#
# Proposed interface for vGPU Migration
# ("[PATCH v3 0/5] Add migration support for VFIO device ")
# https://lists.gnu.org/archive/html/qemu-devel/2019-02/msg05176.html
# Upstreamed commit a8a24f3f6e38 (vfio: UAPI for migration interface
# for device state) in v5.8 (2020-05-29)
#
CODE="
#include <linux/vfio.h>
struct vfio_device_migration_info info;"
compile_check_conftest "$CODE" "NV_VFIO_DEVICE_MIGRATION_INFO_PRESENT" "" "types"
;;
vfio_device_migration_has_start_pfn)
#
# Determine if the 'vfio_device_migration_info' structure has
@@ -5304,6 +5304,67 @@ compile_test() {
compile_check_conftest "$CODE" "NV_ACPI_BUS_GET_DEVICE_PRESENT" "" "functions"
;;
dma_resv_add_fence)
#
# Determine if the dma_resv_add_fence() function is present.
#
# dma_resv_add_excl_fence() and dma_resv_add_shared_fence() were
# removed and replaced with dma_resv_add_fence() by commit
# 73511edf8b19 ("dma-buf: specify usage while adding fences to
# dma_resv obj v7") in linux-next, expected in v5.19-rc1.
#
CODE="
#if defined(NV_LINUX_DMA_RESV_H_PRESENT)
#include <linux/dma-resv.h>
#endif
void conftest_dma_resv_add_fence(void) {
dma_resv_add_fence();
}"
compile_check_conftest "$CODE" "NV_DMA_RESV_ADD_FENCE_PRESENT" "" "functions"
;;
dma_resv_reserve_fences)
#
# Determine if the dma_resv_reserve_fences() function is present.
#
# dma_resv_reserve_shared() was removed and replaced with
# dma_resv_reserve_fences() by commit c8d4c18bfbc4
# ("dma-buf/drivers: make reserving a shared slot mandatory v4") in
# linux-next, expected in v5.19-rc1.
#
CODE="
#if defined(NV_LINUX_DMA_RESV_H_PRESENT)
#include <linux/dma-resv.h>
#endif
void conftest_dma_resv_reserve_fences(void) {
dma_resv_reserve_fences();
}"
compile_check_conftest "$CODE" "NV_DMA_RESV_RESERVE_FENCES_PRESENT" "" "functions"
;;
reservation_object_reserve_shared_has_num_fences_arg)
#
# Determine if reservation_object_reserve_shared() has 'num_fences'
# argument.
#
# reservation_object_reserve_shared() function prototype was updated
# to take 'num_fences' argument by commit ca05359f1e64 ("dma-buf:
# allow reserving more than one shared fence slot") in v4.21-rc1
# (2018-12-14).
#
CODE="
#include <linux/reservation.h>
void conftest_reservation_object_reserve_shared_has_num_fences_arg(
struct reservation_object *obj,
unsigned int num_fences) {
(void) reservation_object_reserve_shared(obj, num_fences);
}"
compile_check_conftest "$CODE" "NV_RESERVATION_OBJECT_RESERVE_SHARED_HAS_NUM_FENCES_ARG" "" "types"
;;
# When adding a new conftest entry, please use the correct format for
# specifying the relevant upstream Linux kernel commit.
#

View File

@@ -65,11 +65,57 @@ static inline void nv_dma_resv_fini(nv_dma_resv_t *obj)
#endif
}
static inline void nv_dma_resv_lock(nv_dma_resv_t *obj,
struct ww_acquire_ctx *ctx)
{
#if defined(NV_LINUX_DMA_RESV_H_PRESENT)
dma_resv_lock(obj, ctx);
#else
ww_mutex_lock(&obj->lock, ctx);
#endif
}
static inline void nv_dma_resv_unlock(nv_dma_resv_t *obj)
{
#if defined(NV_LINUX_DMA_RESV_H_PRESENT)
dma_resv_unlock(obj);
#else
ww_mutex_unlock(&obj->lock);
#endif
}
static inline int nv_dma_resv_reserve_fences(nv_dma_resv_t *obj,
unsigned int num_fences,
NvBool shared)
{
#if defined(NV_DMA_RESV_RESERVE_FENCES_PRESENT)
return dma_resv_reserve_fences(obj, num_fences);
#else
if (shared) {
#if defined(NV_LINUX_DMA_RESV_H_PRESENT)
return dma_resv_reserve_shared(obj, num_fences);
#elif defined(NV_RESERVATION_OBJECT_RESERVE_SHARED_HAS_NUM_FENCES_ARG)
return reservation_object_reserve_shared(obj, num_fences);
#else
unsigned int i;
for (i = 0; i < num_fences; i++) {
reservation_object_reserve_shared(obj);
}
#endif
}
return 0;
#endif
}
static inline void nv_dma_resv_add_excl_fence(nv_dma_resv_t *obj,
nv_dma_fence_t *fence)
{
#if defined(NV_LINUX_DMA_RESV_H_PRESENT)
#if defined(NV_DMA_RESV_ADD_FENCE_PRESENT)
dma_resv_add_fence(obj, fence, DMA_RESV_USAGE_WRITE);
#else
dma_resv_add_excl_fence(obj, fence);
#endif
#else
reservation_object_add_excl_fence(obj, fence);
#endif

View File

@@ -499,9 +499,18 @@ int nv_drm_gem_fence_attach_ioctl(struct drm_device *dev,
goto fence_context_create_fence_failed;
}
nv_dma_resv_add_excl_fence(&nv_gem->resv, fence);
nv_dma_resv_lock(&nv_gem->resv, NULL);
ret = 0;
ret = nv_dma_resv_reserve_fences(&nv_gem->resv, 1, false);
if (ret == 0) {
nv_dma_resv_add_excl_fence(&nv_gem->resv, fence);
} else {
NV_DRM_DEV_LOG_ERR(
nv_dev,
"Failed to reserve fence. Error code: %d", ret);
}
nv_dma_resv_unlock(&nv_gem->resv);
fence_context_create_fence_failed:
nv_drm_gem_object_unreference_unlocked(&nv_gem_fence_context->base);

View File

@@ -115,3 +115,6 @@ NV_CONFTEST_TYPE_COMPILE_TESTS += drm_plane_atomic_check_has_atomic_state_arg
NV_CONFTEST_TYPE_COMPILE_TESTS += drm_device_has_pdev
NV_CONFTEST_TYPE_COMPILE_TESTS += drm_crtc_state_has_no_vblank
NV_CONFTEST_TYPE_COMPILE_TESTS += drm_mode_config_has_allow_fb_modifiers
NV_CONFTEST_TYPE_COMPILE_TESTS += dma_resv_add_fence
NV_CONFTEST_TYPE_COMPILE_TESTS += dma_resv_reserve_fences
NV_CONFTEST_TYPE_COMPILE_TESTS += reservation_object_reserve_shared_has_num_fences_arg

View File

@@ -976,6 +976,7 @@ NvBool nvkms_allow_write_combining(void)
return __rm_ops.system_info.allow_write_combining;
}
#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
/*************************************************************************
* Implementation of sysfs interface to control backlight
*************************************************************************/
@@ -1034,11 +1035,13 @@ static const struct backlight_ops nvkms_backlight_ops = {
.update_status = nvkms_update_backlight_status,
.get_brightness = nvkms_get_backlight_brightness,
};
#endif /* IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) */
struct nvkms_backlight_device*
nvkms_register_backlight(NvU32 gpu_id, NvU32 display_id, void *drv_priv,
NvU32 current_brightness)
{
#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
char name[18];
struct backlight_properties props = {
.brightness = current_brightness,
@@ -1093,15 +1096,20 @@ done:
nvkms_free(gpu_info, NV_MAX_GPUS * sizeof(*gpu_info));
return nvkms_bd;
#else
return NULL;
#endif /* IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) */
}
void nvkms_unregister_backlight(struct nvkms_backlight_device *nvkms_bd)
{
#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
if (nvkms_bd->dev) {
backlight_device_unregister(nvkms_bd->dev);
}
nvkms_free(nvkms_bd, sizeof(*nvkms_bd));
#endif /* IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) */
}
/*************************************************************************

View File

@@ -232,7 +232,7 @@ static inline const struct cpumask *uvm_cpumask_of_node(int node)
#define __GFP_NORETRY 0
#endif
#define NV_UVM_GFP_FLAGS (GFP_KERNEL | __GFP_NORETRY)
#define NV_UVM_GFP_FLAGS (GFP_KERNEL)
#if !defined(NV_ADDRESS_SPACE_INIT_ONCE_PRESENT)
void address_space_init_once(struct address_space *mapping);

View File

@@ -151,7 +151,7 @@ static void maxwell_membar_after_transfer(uvm_push_t *push)
// Flush on transfers only works when paired with a semaphore release. Use a
// host WFI + MEMBAR.
// http://nvbugs/1709888
// Bug 1709888
gpu->parent->host_hal->wait_for_idle(push);
if (uvm_push_get_and_reset_flag(push, UVM_PUSH_FLAG_NEXT_MEMBAR_GPU))

View File

@@ -1805,12 +1805,12 @@ nvswitch_exit
return;
}
nvswitch_procfs_exit();
nvswitch_ctl_exit();
pci_unregister_driver(&nvswitch_pci_driver);
nvswitch_procfs_exit();
cdev_del(&nvswitch.cdev);
unregister_chrdev_region(nvswitch.devno, NVSWITCH_MINOR_COUNT);

View File

@@ -35,29 +35,13 @@ static NV_STATUS nv_acpi_extract_buffer (const union acpi_object *, void *, N
static NV_STATUS nv_acpi_extract_package (const union acpi_object *, void *, NvU32, NvU32 *);
static NV_STATUS nv_acpi_extract_object (const union acpi_object *, void *, NvU32, NvU32 *);
static int nv_acpi_add (struct acpi_device *);
static int nv_acpi_remove (struct acpi_device *device);
static void nv_acpi_event (acpi_handle, u32, void *);
static void nv_acpi_powersource_hotplug_event(acpi_handle, u32, void *);
static acpi_status nv_acpi_find_methods (acpi_handle, u32, void *, void **);
static NV_STATUS nv_acpi_nvif_method (NvU32, NvU32, void *, NvU16, NvU32 *, void *, NvU16 *);
static NV_STATUS nv_acpi_wmmx_method (NvU32, NvU8 *, NvU16 *);
static const struct acpi_device_id nv_video_device_ids[] = {
{
.id = ACPI_VIDEO_HID,
.driver_data = 0,
},
{
.id = "",
.driver_data = 0,
},
};
static struct acpi_driver *nv_acpi_driver;
static acpi_handle nvif_handle = NULL;
static acpi_handle nvif_parent_gpu_handle = NULL;
static acpi_handle wmmx_handle = NULL;
// Used for AC Power Source Hotplug Handling
@@ -81,16 +65,6 @@ static NvBool battery_present = NV_FALSE;
#define ACPI_VIDEO_CLASS "video"
#endif
static const struct acpi_driver nv_acpi_driver_template = {
.name = "NVIDIA ACPI Video Driver",
.class = ACPI_VIDEO_CLASS,
.ids = nv_video_device_ids,
.ops = {
.add = nv_acpi_add,
.remove = nv_acpi_remove,
},
};
static int nv_acpi_get_device_handle(nv_state_t *nv, acpi_handle *dev_handle)
{
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
@@ -151,351 +125,6 @@ void nv_acpi_unregister_notifier(nv_linux_state_t *nvl)
unregister_acpi_notifier(&nvl->acpi_nb);
}
int nv_acpi_init(void)
{
/*
* This function will register the RM with the Linux
* ACPI subsystem.
*/
int status;
nvidia_stack_t *sp = NULL;
NvU32 acpi_event_config = 0;
NV_STATUS rmStatus;
status = nv_kmem_cache_alloc_stack(&sp);
if (status != 0)
{
return status;
}
rmStatus = rm_read_registry_dword(sp, NULL,
NV_REG_REGISTER_FOR_ACPI_EVENTS, &acpi_event_config);
nv_kmem_cache_free_stack(sp);
if ((rmStatus == NV_OK) && (acpi_event_config == 0))
return 0;
if (nv_acpi_driver != NULL)
return -EBUSY;
rmStatus = os_alloc_mem((void **)&nv_acpi_driver,
sizeof(struct acpi_driver));
if (rmStatus != NV_OK)
return -ENOMEM;
memcpy((void *)nv_acpi_driver, (void *)&nv_acpi_driver_template,
sizeof(struct acpi_driver));
status = acpi_bus_register_driver(nv_acpi_driver);
if (status < 0)
{
nv_printf(NV_DBG_INFO,
"NVRM: nv_acpi_init: acpi_bus_register_driver() failed (%d)!\n", status);
os_free_mem(nv_acpi_driver);
nv_acpi_driver = NULL;
}
return status;
}
int nv_acpi_uninit(void)
{
nvidia_stack_t *sp = NULL;
NvU32 acpi_event_config = 0;
NV_STATUS rmStatus;
int rc;
rc = nv_kmem_cache_alloc_stack(&sp);
if (rc != 0)
{
return rc;
}
rmStatus = rm_read_registry_dword(sp, NULL,
NV_REG_REGISTER_FOR_ACPI_EVENTS, &acpi_event_config);
nv_kmem_cache_free_stack(sp);
if ((rmStatus == NV_OK) && (acpi_event_config == 0))
return 0;
if (nv_acpi_driver == NULL)
return -ENXIO;
acpi_bus_unregister_driver(nv_acpi_driver);
os_free_mem(nv_acpi_driver);
nv_acpi_driver = NULL;
return 0;
}
static int nv_acpi_add(struct acpi_device *device)
{
/*
* This function will cause RM to initialize the things it needs for acpi interaction
* on the display device.
*/
int status = -1;
NV_STATUS rmStatus = NV_ERR_GENERIC;
nv_acpi_t *pNvAcpiObject = NULL;
union acpi_object control_argument_0 = { ACPI_TYPE_INTEGER };
struct acpi_object_list control_argument_list = { 0, NULL };
nvidia_stack_t *sp = NULL;
struct list_head *node, *next;
unsigned long long device_id = 0;
int device_counter = 0;
status = nv_kmem_cache_alloc_stack(&sp);
if (status != 0)
{
return status;
}
// allocate data structure we need
rmStatus = os_alloc_mem((void **) &pNvAcpiObject, sizeof(nv_acpi_t));
if (rmStatus != NV_OK)
{
nv_kmem_cache_free_stack(sp);
nv_printf(NV_DBG_ERRORS,
"NVRM: nv_acpi_add: failed to allocate ACPI device management data!\n");
return -ENOMEM;
}
os_mem_set((void *)pNvAcpiObject, 0, sizeof(nv_acpi_t));
device->driver_data = pNvAcpiObject;
pNvAcpiObject->device = device;
pNvAcpiObject->sp = sp;
// grab handles to all the important nodes representing devices
list_for_each_safe(node, next, &device->children)
{
struct acpi_device *dev =
list_entry(node, struct acpi_device, node);
if (!dev)
continue;
if (device_counter == NV_MAXNUM_DISPLAY_DEVICES)
{
nv_printf(NV_DBG_ERRORS,
"NVRM: nv_acpi_add: Total number of devices cannot exceed %d\n",
NV_MAXNUM_DISPLAY_DEVICES);
break;
}
status =
acpi_evaluate_integer(dev->handle, "_ADR", NULL, &device_id);
if (ACPI_FAILURE(status))
/* Couldnt query device_id for this device */
continue;
device_id = (device_id & 0xffff);
if ((device_id != 0x100) && /* Not a known CRT device-id */
(device_id != 0x200) && /* Not a known TV device-id */
(device_id != 0x0110) && (device_id != 0x0118) && (device_id != 0x0400) && /* Not an LCD*/
(device_id != 0x0111) && (device_id != 0x0120) && (device_id != 0x0300)) /* Not a known DVI device-id */
{
/* This isnt a known device Id.
Do default switching on this system. */
pNvAcpiObject->default_display_mask = 1;
break;
}
pNvAcpiObject->pNvVideo[device_counter].dev_id = device_id;
pNvAcpiObject->pNvVideo[device_counter].dev_handle = dev->handle;
device_counter++;
}
// arg 0, bits 1:0, 0 = enable events
control_argument_0.integer.type = ACPI_TYPE_INTEGER;
control_argument_0.integer.value = 0x0;
// listify it
control_argument_list.count = 1;
control_argument_list.pointer = &control_argument_0;
// _DOS method takes 1 argument and returns nothing
status = acpi_evaluate_object(device->handle, "_DOS", &control_argument_list, NULL);
if (ACPI_FAILURE(status))
{
nv_printf(NV_DBG_INFO,
"NVRM: nv_acpi_add: failed to enable display switch events (%d)!\n", status);
}
status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
nv_acpi_event, pNvAcpiObject);
if (ACPI_FAILURE(status))
{
nv_printf(NV_DBG_INFO,
"NVRM: nv_acpi_add: failed to install event notification handler (%d)!\n", status);
}
else
{
try_module_get(THIS_MODULE);
pNvAcpiObject->notify_handler_installed = 1;
}
return 0;
}
static int nv_acpi_remove(struct acpi_device *device)
{
/*
* This function will cause RM to relinquish control of the VGA ACPI device.
*/
acpi_status status;
union acpi_object control_argument_0 = { ACPI_TYPE_INTEGER };
struct acpi_object_list control_argument_list = { 0, NULL };
nv_acpi_t *pNvAcpiObject = device->driver_data;
pNvAcpiObject->default_display_mask = 0;
// arg 0, bits 1:0, 1 = disable events
control_argument_0.integer.type = ACPI_TYPE_INTEGER;
control_argument_0.integer.value = 0x1;
// listify it
control_argument_list.count = 1;
control_argument_list.pointer = &control_argument_0;
// _DOS method takes 1 argument and returns nothing
status = acpi_evaluate_object(device->handle, "_DOS", &control_argument_list, NULL);
if (ACPI_FAILURE(status))
{
nv_printf(NV_DBG_INFO,
"NVRM: nv_acpi_remove: failed to disable display switch events (%d)!\n", status);
}
if (pNvAcpiObject->notify_handler_installed)
{
// remove event notifier
status = acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, nv_acpi_event);
}
if (pNvAcpiObject->notify_handler_installed &&
ACPI_FAILURE(status))
{
nv_printf(NV_DBG_INFO,
"NVRM: nv_acpi_remove: failed to remove event notification handler (%d)!\n", status);
}
else
{
nv_kmem_cache_free_stack(pNvAcpiObject->sp);
os_free_mem((void *)pNvAcpiObject);
module_put(THIS_MODULE);
device->driver_data = NULL;
}
return status;
}
/*
* The ACPI specification defines IDs for various ACPI video
* extension events like display switch events, AC/battery
* events, docking events, etc..
* Whenever an ACPI event is received by the corresponding
* event handler installed within the core NVIDIA driver, the
* code can verify the event ID before processing it.
*/
#define ACPI_DISPLAY_DEVICE_CHANGE_EVENT 0x80
#define NVIF_NOTIFY_DISPLAY_DETECT 0xCB
#define NVIF_DISPLAY_DEVICE_CHANGE_EVENT NVIF_NOTIFY_DISPLAY_DETECT
static void nv_acpi_event(acpi_handle handle, u32 event_type, void *data)
{
/*
* This function will handle acpi events from the linux kernel, used
* to detect notifications from the VGA device.
*/
nv_acpi_t *pNvAcpiObject = data;
u32 event_val = 0;
unsigned long long state;
int status = 0;
int device_counter = 0;
if (event_type == NVIF_DISPLAY_DEVICE_CHANGE_EVENT)
{
/* We are getting NVIF events on this machine. We arent putting a very
extensive handling in-place to communicate back with SBIOS, know
the next enabled devices, and then do the switch. We just
pass a default display switch event, so that X-driver decides
the switching policy itself. */
rm_system_event(pNvAcpiObject->sp, NV_SYSTEM_ACPI_DISPLAY_SWITCH_EVENT, 0);
}
if (event_type == ACPI_DISPLAY_DEVICE_CHANGE_EVENT)
{
if (pNvAcpiObject->default_display_mask != 1)
{
while ((device_counter < NV_MAXNUM_DISPLAY_DEVICES) &&
(pNvAcpiObject->pNvVideo[device_counter].dev_handle))
{
acpi_handle dev_handle = pNvAcpiObject->pNvVideo[device_counter].dev_handle;
int dev_id = pNvAcpiObject->pNvVideo[device_counter].dev_id;
status = acpi_evaluate_integer(dev_handle,
"_DGS",
NULL,
&state);
if (ACPI_FAILURE(status))
{
nv_printf(NV_DBG_INFO,
"NVRM: nv_acpi_event: failed to query _DGS method for display device 0x%x\n",
dev_id);
}
else if (state)
{
/* Check if the device is a CRT ...*/
if (dev_id == 0x0100)
{
event_val |= NV_HOTKEY_STATUS_DISPLAY_ENABLE_CRT;
}
/* device-id for a TV */
else if (dev_id == 0x0200)
{
event_val |= NV_HOTKEY_STATUS_DISPLAY_ENABLE_TV;
}
else if ((dev_id == 0x0110) || /* device id for internal LCD */
(dev_id == 0x0118) || /* alternate ACPI ID for the
internal LCD */
(dev_id == 0x0400)) /* ACPI spec 3.0 specified
device id for a internal LCD*/
{
event_val |= NV_HOTKEY_STATUS_DISPLAY_ENABLE_LCD;
}
else if ((dev_id == 0x0111) || /* the set
of possible device-ids for a DFP */
(dev_id == 0x0120) ||
(dev_id == 0x0300)) /* ACPI spec 3.0 specified
device id for non-LVDS DFP */
{
event_val |= NV_HOTKEY_STATUS_DISPLAY_ENABLE_DFP;
}
}
device_counter++;
}
}
nv_printf(NV_DBG_INFO,
"NVRM: nv_acpi_event: Event-type 0x%x, Event-val 0x%x\n",
event_type, event_val);
rm_system_event(pNvAcpiObject->sp, NV_SYSTEM_ACPI_DISPLAY_SWITCH_EVENT, event_val);
}
// no unsubscription or re-enable necessary. Once DOD has been set, we are go.
// once we are subscribed to ACPI events, we don't have to re-subscribe unless
// unsubscribe.
}
NV_STATUS NV_API_CALL nv_acpi_get_powersource(NvU32 *ac_plugged)
{
unsigned long long val;
@@ -543,14 +172,14 @@ static void nv_acpi_powersource_hotplug_event(acpi_handle handle, u32 event_type
*/
/* Do the necessary allocations and install notifier "handler" on the device-node "device" */
static nv_acpi_t* nv_install_notifier(struct acpi_device *device, acpi_notify_handler handler)
static nv_acpi_t* nv_install_notifier(struct acpi_handle *handle, acpi_notify_handler handler)
{
nvidia_stack_t *sp = NULL;
nv_acpi_t *pNvAcpiObject = NULL;
NV_STATUS rmStatus = NV_ERR_GENERIC;
acpi_status status = -1;
if (!device)
if (!handle)
return NULL;
if (nv_kmem_cache_alloc_stack(&sp) != 0)
@@ -564,11 +193,11 @@ static nv_acpi_t* nv_install_notifier(struct acpi_device *device, acpi_notify_ha
os_mem_set((void *)pNvAcpiObject, 0, sizeof(nv_acpi_t));
// store a device reference in our object
pNvAcpiObject->device = device;
// store a handle reference in our object
pNvAcpiObject->handle = handle;
pNvAcpiObject->sp = sp;
status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY,
handler, pNvAcpiObject);
if (!ACPI_FAILURE(status))
{
@@ -592,7 +221,7 @@ static void nv_uninstall_notifier(nv_acpi_t *pNvAcpiObject, acpi_notify_handler
if (pNvAcpiObject && pNvAcpiObject->notify_handler_installed)
{
status = acpi_remove_notify_handler(pNvAcpiObject->device->handle, ACPI_DEVICE_NOTIFY, handler);
status = acpi_remove_notify_handler(pNvAcpiObject->handle, ACPI_DEVICE_NOTIFY, handler);
if (ACPI_FAILURE(status))
{
nv_printf(NV_DBG_INFO,
@@ -616,56 +245,22 @@ static void nv_uninstall_notifier(nv_acpi_t *pNvAcpiObject, acpi_notify_handler
void NV_API_CALL nv_acpi_methods_init(NvU32 *handlesPresent)
{
#if defined(NV_ACPI_BUS_GET_DEVICE_PRESENT)
struct acpi_device *device = NULL;
int retVal = -1;
#endif
if (!handlesPresent) // Caller passed us invalid pointer.
return;
*handlesPresent = 0;
NV_ACPI_WALK_NAMESPACE(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, nv_acpi_find_methods, NULL, NULL);
#if defined(NV_ACPI_BUS_GET_DEVICE_PRESENT)
if (nvif_handle)
{
*handlesPresent = NV_ACPI_NVIF_HANDLE_PRESENT;
do
{
if (!nvif_parent_gpu_handle) /* unknown error */
break;
retVal = acpi_bus_get_device(nvif_parent_gpu_handle, &device);
if (ACPI_FAILURE(retVal) || !device)
break;
if (device->driver_data)
{
nvif_parent_gpu_handle = NULL;
break; /* Someone else has already populated this device
nodes' structures. So nothing more to be done */
}
device->driver_data = nv_install_notifier(device, nv_acpi_event);
if (!device->driver_data)
nvif_parent_gpu_handle = NULL;
} while (0);
}
#endif
if (wmmx_handle)
*handlesPresent = *handlesPresent | NV_ACPI_WMMX_HANDLE_PRESENT;
#if defined(NV_ACPI_BUS_GET_DEVICE_PRESENT)
if (psr_handle)
{
// Since _PSR is not a per-GPU construct we only need to register a
@@ -673,15 +268,9 @@ void NV_API_CALL nv_acpi_methods_init(NvU32 *handlesPresent)
// devices
if (psr_nv_acpi_object == NULL)
{
retVal = acpi_bus_get_device(psr_device_handle, &device);
if (!(ACPI_FAILURE(retVal) || !device))
{
psr_nv_acpi_object = nv_install_notifier(device, nv_acpi_powersource_hotplug_event);
}
psr_nv_acpi_object = nv_install_notifier(psr_device_handle, nv_acpi_powersource_hotplug_event);
}
}
#endif
return;
}
@@ -698,7 +287,6 @@ acpi_status nv_acpi_find_methods(
if (!acpi_get_handle(handle, "NVIF", &method_handle))
{
nvif_handle = method_handle;
nvif_parent_gpu_handle = handle;
}
if (!acpi_get_handle(handle, "WMMX", &method_handle))
@@ -717,8 +305,6 @@ acpi_status nv_acpi_find_methods(
void NV_API_CALL nv_acpi_methods_uninit(void)
{
struct acpi_device *device = NULL;
nvif_handle = NULL;
wmmx_handle = NULL;
@@ -730,20 +316,6 @@ void NV_API_CALL nv_acpi_methods_uninit(void)
psr_device_handle = NULL;
psr_nv_acpi_object = NULL;
}
if (nvif_parent_gpu_handle == NULL)
return;
#if defined(NV_ACPI_BUS_GET_DEVICE_PRESENT)
acpi_bus_get_device(nvif_parent_gpu_handle, &device);
nv_uninstall_notifier(device->driver_data, nv_acpi_event);
#endif
device->driver_data = NULL;
nvif_parent_gpu_handle = NULL;
return;
}
static NV_STATUS nv_acpi_extract_integer(
@@ -1763,16 +1335,6 @@ NvBool NV_API_CALL nv_acpi_is_battery_present(void)
#else // NV_LINUX_ACPI_EVENTS_SUPPORTED
int nv_acpi_init(void)
{
return 0;
}
int nv_acpi_uninit(void)
{
return 0;
}
void NV_API_CALL nv_acpi_methods_init(NvU32 *handlePresent)
{
*handlePresent = 0;

View File

@@ -25,6 +25,7 @@
#include "os-interface.h"
#include "nv-linux.h"
#include "nv-reg.h"
#define NV_DMA_DEV_PRINTF(debuglevel, dma_dev, format, ... ) \
nv_printf(debuglevel, "NVRM: %s: " format, \
@@ -32,6 +33,8 @@
NULL), \
## __VA_ARGS__)
NvU32 nv_dma_remap_peer_mmio = NV_DMA_REMAP_PEER_MMIO_ENABLE;
NV_STATUS nv_create_dma_map_scatterlist (nv_dma_map_t *dma_map);
void nv_destroy_dma_map_scatterlist(nv_dma_map_t *dma_map);
NV_STATUS nv_map_dma_map_scatterlist (nv_dma_map_t *dma_map);
@@ -766,11 +769,16 @@ NV_STATUS NV_API_CALL nv_dma_unmap_alloc
return status;
}
static NvBool nv_dma_is_map_resource_implemented
static NvBool nv_dma_use_map_resource
(
nv_dma_device_t *dma_dev
)
{
if (nv_dma_remap_peer_mmio == NV_DMA_REMAP_PEER_MMIO_DISABLE)
{
return NV_FALSE;
}
#if defined(NV_DMA_MAP_RESOURCE_PRESENT)
const struct dma_map_ops *ops = get_dma_ops(dma_dev->dev);
@@ -833,7 +841,7 @@ NV_STATUS NV_API_CALL nv_dma_map_peer
return NV_ERR_INVALID_REQUEST;
}
if (nv_dma_is_map_resource_implemented(dma_dev))
if (nv_dma_use_map_resource(dma_dev))
{
status = nv_dma_map_mmio(dma_dev, page_count, va);
}
@@ -858,7 +866,7 @@ void NV_API_CALL nv_dma_unmap_peer
NvU64 va
)
{
if (nv_dma_is_map_resource_implemented(dma_dev))
if (nv_dma_use_map_resource(dma_dev))
{
nv_dma_unmap_mmio(dma_dev, page_count, va);
}
@@ -873,29 +881,28 @@ NV_STATUS NV_API_CALL nv_dma_map_mmio
)
{
#if defined(NV_DMA_MAP_RESOURCE_PRESENT)
NvU64 mmio_addr;
BUG_ON(!va);
mmio_addr = *va;
*va = dma_map_resource(dma_dev->dev, mmio_addr, page_count * PAGE_SIZE,
DMA_BIDIRECTIONAL, 0);
if (dma_mapping_error(dma_dev->dev, *va))
if (nv_dma_use_map_resource(dma_dev))
{
NV_DMA_DEV_PRINTF(NV_DBG_ERRORS, dma_dev,
"Failed to DMA map MMIO range [0x%llx-0x%llx]\n",
mmio_addr, mmio_addr + page_count * PAGE_SIZE - 1);
return NV_ERR_OPERATING_SYSTEM;
NvU64 mmio_addr = *va;
*va = dma_map_resource(dma_dev->dev, mmio_addr, page_count * PAGE_SIZE,
DMA_BIDIRECTIONAL, 0);
if (dma_mapping_error(dma_dev->dev, *va))
{
NV_DMA_DEV_PRINTF(NV_DBG_ERRORS, dma_dev,
"Failed to DMA map MMIO range [0x%llx-0x%llx]\n",
mmio_addr, mmio_addr + page_count * PAGE_SIZE - 1);
return NV_ERR_OPERATING_SYSTEM;
}
}
/*
* The default implementation passes through the source address
* without failing. Adjust it using the DMA start address to keep RM's
* validation schemes happy.
*/
if (!nv_dma_is_map_resource_implemented(dma_dev))
else
{
/*
* If dma_map_resource is not available, pass through the source address
* without failing. Further, adjust it using the DMA start address to
* keep RM's validation schemes happy.
*/
*va = *va + dma_dev->addressable_range.start;
}
@@ -915,15 +922,13 @@ void NV_API_CALL nv_dma_unmap_mmio
)
{
#if defined(NV_DMA_MAP_RESOURCE_PRESENT)
if (!nv_dma_is_map_resource_implemented(dma_dev))
{
va = va - dma_dev->addressable_range.start;
}
nv_dma_nvlink_addr_decompress(dma_dev, &va, page_count, NV_TRUE);
dma_unmap_resource(dma_dev->dev, va, page_count * PAGE_SIZE,
DMA_BIDIRECTIONAL, 0);
if (nv_dma_use_map_resource(dma_dev))
{
dma_unmap_resource(dma_dev->dev, va, page_count * PAGE_SIZE,
DMA_BIDIRECTIONAL, 0);
}
#endif
}

View File

@@ -48,6 +48,7 @@ typedef struct nv_dma_buf_file_private
nv_dma_buf_mem_handle_t *handles;
NvU64 bar1_va_ref_count;
void *mig_info;
NvBool can_mmap;
} nv_dma_buf_file_private_t;
static void
@@ -562,6 +563,8 @@ nv_dma_buf_mmap(
struct vm_area_struct *vma
)
{
// TODO: Check can_mmap flag
return -ENOTSUPP;
}
@@ -674,6 +677,7 @@ nv_dma_buf_create(
priv->total_objects = params->totalObjects;
priv->total_size = params->totalSize;
priv->nv = nv;
priv->can_mmap = NV_FALSE;
rc = nv_kmem_cache_alloc_stack(&sp);
if (rc != 0)
@@ -792,6 +796,15 @@ nv_dma_buf_reuse(
return NV_ERR_OPERATING_SYSTEM;
}
priv = buf->priv;
if (priv == NULL)

View File

@@ -301,23 +301,6 @@
#define __NV_ENABLE_MSI EnableMSI
#define NV_REG_ENABLE_MSI NV_REG_STRING(__NV_ENABLE_MSI)
/*
* Option: RegisterForACPIEvents
*
* Description:
*
* When this option is enabled, the NVIDIA driver will register with the
* ACPI subsystem to receive notification of ACPI events.
*
* Possible values:
*
* 1 - register for ACPI events (default)
* 0 - do not register for ACPI events
*/
#define __NV_REGISTER_FOR_ACPI_EVENTS RegisterForACPIEvents
#define NV_REG_REGISTER_FOR_ACPI_EVENTS NV_REG_STRING(__NV_REGISTER_FOR_ACPI_EVENTS)
/*
* Option: EnablePCIeGen3
*
@@ -819,6 +802,30 @@
#define NV_REG_OPENRM_ENABLE_UNSUPPORTED_GPUS_ENABLE 0x00000001
#define NV_REG_OPENRM_ENABLE_UNSUPPORTED_GPUS_DEFAULT NV_REG_OPENRM_ENABLE_UNSUPPORTED_GPUS_DISABLE
/*
* Option: NVreg_DmaRemapPeerMmio
*
* Description:
*
* When this option is enabled, the NVIDIA driver will use device driver
* APIs provided by the Linux kernel for DMA-remapping part of a device's
* MMIO region to another device, creating e.g., IOMMU mappings as necessary.
* When this option is disabled, the NVIDIA driver will instead only apply a
* fixed offset, which may be zero, to CPU physical addresses to produce the
* DMA address for the peer's MMIO region, and no IOMMU mappings will be
* created.
*
* This option only affects peer MMIO DMA mappings, and not system memory
* mappings.
*
* Possible Values:
* 0 = disable dynamic DMA remapping of peer MMIO regions
* 1 = enable dynamic DMA remapping of peer MMIO regions (default)
*/
#define __NV_DMA_REMAP_PEER_MMIO DmaRemapPeerMmio
#define NV_DMA_REMAP_PEER_MMIO NV_REG_STRING(__NV_DMA_REMAP_PEER_MMIO)
#define NV_DMA_REMAP_PEER_MMIO_DISABLE 0x00000000
#define NV_DMA_REMAP_PEER_MMIO_ENABLE 0x00000001
#if defined(NV_DEFINE_REGISTRY_KEY_TABLE)
@@ -834,7 +841,6 @@ NV_DEFINE_REG_ENTRY(__NV_DEVICE_FILE_GID, 0);
NV_DEFINE_REG_ENTRY(__NV_DEVICE_FILE_MODE, 0666);
NV_DEFINE_REG_ENTRY(__NV_INITIALIZE_SYSTEM_MEMORY_ALLOCATIONS, 1);
NV_DEFINE_REG_ENTRY(__NV_USE_PAGE_ATTRIBUTE_TABLE, ~0);
NV_DEFINE_REG_ENTRY(__NV_REGISTER_FOR_ACPI_EVENTS, 1);
NV_DEFINE_REG_ENTRY(__NV_ENABLE_PCIE_GEN3, 0);
NV_DEFINE_REG_ENTRY(__NV_ENABLE_MSI, 1);
NV_DEFINE_REG_ENTRY(__NV_TCE_BYPASS_MODE, NV_TCE_BYPASS_MODE_DEFAULT);
@@ -871,6 +877,7 @@ NV_DEFINE_REG_STRING_ENTRY(__NV_RM_MSG, NULL);
NV_DEFINE_REG_STRING_ENTRY(__NV_GPU_BLACKLIST, NULL);
NV_DEFINE_REG_STRING_ENTRY(__NV_TEMPORARY_FILE_PATH, NULL);
NV_DEFINE_REG_STRING_ENTRY(__NV_EXCLUDED_GPUS, NULL);
NV_DEFINE_REG_ENTRY(__NV_DMA_REMAP_PEER_MMIO, NV_DMA_REMAP_PEER_MMIO_ENABLE);
/*
*----------------registry database definition----------------------
@@ -893,7 +900,6 @@ nv_parm_t nv_parms[] = {
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_INITIALIZE_SYSTEM_MEMORY_ALLOCATIONS),
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_USE_PAGE_ATTRIBUTE_TABLE),
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_MSI),
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_REGISTER_FOR_ACPI_EVENTS),
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_PCIE_GEN3),
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_MEMORY_POOL_SIZE),
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_KMALLOC_HEAP_MAX_SIZE),
@@ -918,6 +924,7 @@ nv_parm_t nv_parms[] = {
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_GPU_FIRMWARE_LOGS),
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_DBG_BREAKPOINT),
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_OPENRM_ENABLE_UNSUPPORTED_GPUS),
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_DMA_REMAP_PEER_MMIO),
{NULL, NULL}
};

View File

@@ -114,6 +114,7 @@ nv_linux_state_t *nv_linux_devices;
* And one for the control device
*/
nv_linux_state_t nv_ctl_device = { { 0 } };
extern NvU32 nv_dma_remap_peer_mmio;
nv_kthread_q_t nv_kthread_q;
nv_kthread_q_t nv_deferred_close_kthread_q;
@@ -571,6 +572,12 @@ nv_registry_keys_init(nv_stack_t *sp)
WARN_ON(status != NV_OK);
}
}
status = rm_read_registry_dword(sp, nv, NV_DMA_REMAP_PEER_MMIO, &data);
if (status == NV_OK)
{
nv_dma_remap_peer_mmio = data;
}
}
static void __init
@@ -2660,7 +2667,6 @@ nvidia_ctl_open(
nv_linux_state_t *nvl = &nv_ctl_device;
nv_state_t *nv = NV_STATE_PTR(nvl);
nv_linux_file_private_t *nvlfp = NV_GET_LINUX_FILE_PRIVATE(file);
static int count = 0;
nv_printf(NV_DBG_INFO, "NVRM: nvidia_ctl_open\n");
@@ -2672,13 +2678,6 @@ nvidia_ctl_open(
if (NV_ATOMIC_READ(nvl->usage_count) == 0)
{
nv->flags |= (NV_FLAG_OPEN | NV_FLAG_CONTROL);
if ((nv_acpi_init() < 0) &&
(count++ < NV_MAX_RECURRING_WARNING_MESSAGES))
{
nv_printf(NV_DBG_ERRORS,
"NVRM: failed to register with the ACPI subsystem!\n");
}
}
NV_ATOMIC_INC(nvl->usage_count);
@@ -2702,7 +2701,6 @@ nvidia_ctl_close(
nv_state_t *nv = NV_STATE_PTR(nvl);
nv_linux_file_private_t *nvlfp = NV_GET_LINUX_FILE_PRIVATE(file);
nvidia_stack_t *sp = nvlfp->sp;
static int count = 0;
unsigned int i;
nv_printf(NV_DBG_INFO, "NVRM: nvidia_ctl_close\n");
@@ -2711,13 +2709,6 @@ nvidia_ctl_close(
if (NV_ATOMIC_DEC_AND_TEST(nvl->usage_count))
{
nv->flags &= ~NV_FLAG_OPEN;
if ((nv_acpi_uninit() < 0) &&
(count++ < NV_MAX_RECURRING_WARNING_MESSAGES))
{
nv_printf(NV_DBG_ERRORS,
"NVRM: failed to unregister from the ACPI subsystem!\n");
}
}
up(&nvl->ldata_lock);