linux/drivers/gpu/drm/nouveau/nouveau_drm.c

/*
 * Copyright 2012 Red Hat Inc.
 *
 * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
 *
 * Authors: Ben Skeggs
 */

#include <linux/delay.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/vga_switcheroo.h>
#include <linux/mmu_notifier.h>
#include <linux/dynamic_debug.h>

#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
#include <drm/drm_fbdev_ttm.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_vblank.h>

#include <core/gpuobj.h>
#include <core/option.h>
#include <core/pci.h>
#include <core/tegra.h>

#include <nvif/driver.h>
#include <nvif/fifo.h>
#include <nvif/push006c.h>
#include <nvif/user.h>

#include <nvif/class.h>
#include <nvif/cl0002.h>

#include "nouveau_drv.h"
#include "nouveau_dma.h"
#include "nouveau_ttm.h"
#include "nouveau_gem.h"
#include "nouveau_vga.h"
#include "nouveau_led.h"
#include "nouveau_hwmon.h"
#include "nouveau_acpi.h"
#include "nouveau_bios.h"
#include "nouveau_ioctl.h"
#include "nouveau_abi16.h"
#include "nouveau_fence.h"
#include "nouveau_debugfs.h"
#include "nouveau_usif.h"
#include "nouveau_connector.h"
#include "nouveau_platform.h"
#include "nouveau_svm.h"
#include "nouveau_dmem.h"
#include "nouveau_exec.h"
#include "nouveau_uvmm.h"
#include "nouveau_sched.h"

DECLARE_DYNDBG_CLASSMAP();

MODULE_PARM_DESC();
static char *nouveau_config;
module_param_named(config, nouveau_config, charp, 0400);

MODULE_PARM_DESC();
static char *nouveau_debug;
module_param_named(debug, nouveau_debug, charp, 0400);

MODULE_PARM_DESC();
static int nouveau_noaccel =;
module_param_named(noaccel, nouveau_noaccel, int, 0400);

MODULE_PARM_DESC();
int nouveau_modeset =;
module_param_named(modeset, nouveau_modeset, int, 0400);

MODULE_PARM_DESC();
static int nouveau_atomic =;
module_param_named(atomic, nouveau_atomic, int, 0400);

MODULE_PARM_DESC();
static int nouveau_runtime_pm =;
module_param_named(runpm, nouveau_runtime_pm, int, 0400);

static struct drm_driver driver_stub;
static struct drm_driver driver_pci;
static struct drm_driver driver_platform;

static u64
nouveau_pci_name(struct pci_dev *pdev)
{}

static u64
nouveau_platform_name(struct platform_device *platformdev)
{}

static u64
nouveau_name(struct drm_device *dev)
{}

static inline bool
nouveau_cli_work_ready(struct dma_fence *fence)
{}

static void
nouveau_cli_work(struct work_struct *w)
{}

static void
nouveau_cli_work_fence(struct dma_fence *fence, struct dma_fence_cb *cb)
{}

void
nouveau_cli_work_queue(struct nouveau_cli *cli, struct dma_fence *fence,
		       struct nouveau_cli_work *work)
{}

static void
nouveau_cli_fini(struct nouveau_cli *cli)
{}

static int
nouveau_cli_init(struct nouveau_drm *drm, const char *sname,
		 struct nouveau_cli *cli)
{}

static void
nouveau_accel_ce_fini(struct nouveau_drm *drm)
{}

static void
nouveau_accel_ce_init(struct nouveau_drm *drm)
{}

static void
nouveau_accel_gr_fini(struct nouveau_drm *drm)
{}

static void
nouveau_accel_gr_init(struct nouveau_drm *drm)
{}

static void
nouveau_accel_fini(struct nouveau_drm *drm)
{}

static void
nouveau_accel_init(struct nouveau_drm *drm)
{}

static void __printf(2, 3)
nouveau_drm_errorf(struct nvif_object *object, const char *fmt, ...)
{}

static void __printf(2, 3)
nouveau_drm_debugf(struct nvif_object *object, const char *fmt, ...)
{}

static const struct nvif_parent_func
nouveau_parent =;

static int
nouveau_drm_device_init(struct drm_device *dev)
{}

static void
nouveau_drm_device_fini(struct drm_device *dev)
{}

/*
 * On some Intel PCIe bridge controllers doing a
 * D0 -> D3hot -> D3cold -> D0 sequence causes Nvidia GPUs to not reappear.
 * Skipping the intermediate D3hot step seems to make it work again. This is
 * probably caused by not meeting the expectation the involved AML code has
 * when the GPU is put into D3hot state before invoking it.
 *
 * This leads to various manifestations of this issue:
 *  - AML code execution to power on the GPU hits an infinite loop (as the
 *    code waits on device memory to change).
 *  - kernel crashes, as all PCI reads return -1, which most code isn't able
 *    to handle well enough.
 *
 * In all cases dmesg will contain at least one line like this:
 * 'nouveau 0000:01:00.0: Refused to change power state, currently in D3'
 * followed by a lot of nouveau timeouts.
 *
 * In the \_SB.PCI0.PEG0.PG00._OFF code deeper down writes bit 0x80 to the not
 * documented PCI config space register 0x248 of the Intel PCIe bridge
 * controller (0x1901) in order to change the state of the PCIe link between
 * the PCIe port and the GPU. There are alternative code paths using other
 * registers, which seem to work fine (executed pre Windows 8):
 *  - 0xbc bit 0x20 (publicly available documentation claims 'reserved')
 *  - 0xb0 bit 0x10 (link disable)
 * Changing the conditions inside the firmware by poking into the relevant
 * addresses does resolve the issue, but it seemed to be ACPI private memory
 * and not any device accessible memory at all, so there is no portable way of
 * changing the conditions.
 * On a XPS 9560 that means bits [0,3] on \CPEX need to be cleared.
 *
 * The only systems where this behavior can be seen are hybrid graphics laptops
 * with a secondary Nvidia Maxwell, Pascal or Turing GPU. It's unclear whether
 * this issue only occurs in combination with listed Intel PCIe bridge
 * controllers and the mentioned GPUs or other devices as well.
 *
 * documentation on the PCIe bridge controller can be found in the
 * "7th Generation Intel® Processor Families for H Platforms Datasheet Volume 2"
 * Section "12 PCI Express* Controller (x16) Registers"
 */

static void quirk_broken_nv_runpm(struct pci_dev *pdev)
{}

static int nouveau_drm_probe(struct pci_dev *pdev,
			     const struct pci_device_id *pent)
{}

void
nouveau_drm_device_remove(struct drm_device *dev)
{}

static void
nouveau_drm_remove(struct pci_dev *pdev)
{}

static int
nouveau_do_suspend(struct drm_device *dev, bool runtime)
{}

static int
nouveau_do_resume(struct drm_device *dev, bool runtime)
{}

int
nouveau_pmops_suspend(struct device *dev)
{}

int
nouveau_pmops_resume(struct device *dev)
{}

static int
nouveau_pmops_freeze(struct device *dev)
{}

static int
nouveau_pmops_thaw(struct device *dev)
{}

bool
nouveau_pmops_runtime(void)
{}

static int
nouveau_pmops_runtime_suspend(struct device *dev)
{}

static int
nouveau_pmops_runtime_resume(struct device *dev)
{}

static int
nouveau_pmops_runtime_idle(struct device *dev)
{}

static int
nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
{}

static void
nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
{}

static const struct drm_ioctl_desc
nouveau_ioctls[] =;

long
nouveau_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{}

static const struct file_operations
nouveau_driver_fops =;

static struct drm_driver
driver_stub =;

static struct pci_device_id
nouveau_drm_pci_table[] =;

static void nouveau_display_options(void)
{}

static const struct dev_pm_ops nouveau_pm_ops =;

static struct pci_driver
nouveau_drm_pci_driver =;

struct drm_device *
nouveau_platform_device_create(const struct nvkm_device_tegra_func *func,
			       struct platform_device *pdev,
			       struct nvkm_device **pdevice)
{}

static int __init
nouveau_drm_init(void)
{}

static void __exit
nouveau_drm_exit(void)
{}

module_init();
module_exit(nouveau_drm_exit);

MODULE_DEVICE_TABLE(pci, nouveau_drm_pci_table);
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();