mirror of
https://github.com/NVIDIA/open-gpu-kernel-modules.git
synced 2026-02-02 06:29:47 +00:00
515.48.07
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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}
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user