diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_drv.h')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 271 |
1 files changed, 226 insertions, 45 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 822fe1d4d35e..0e409414f44d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: MIT */ #ifndef __NOUVEAU_DRV_H__ #define __NOUVEAU_DRV_H__ @@ -5,11 +6,10 @@ #define DRIVER_EMAIL "nouveau@lists.freedesktop.org" #define DRIVER_NAME "nouveau" -#define DRIVER_DESC "nVidia Riva/TNT/GeForce/Quadro/Tesla" -#define DRIVER_DATE "20120801" +#define DRIVER_DESC "nVidia Riva/TNT/GeForce/Quadro/Tesla/Tegra K1+" #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 3 +#define DRIVER_MINOR 4 #define DRIVER_PATCHLEVEL 1 /* @@ -35,6 +35,8 @@ * programs that get directly linked with NVKM. * 1.3.1: * - implemented limited ABI16/NVIF interop + * 1.4.1: + * - add variable page sizes and compression for Turing+ */ #include <linux/notifier.h> @@ -42,25 +44,30 @@ #include <nvif/client.h> #include <nvif/device.h> #include <nvif/ioctl.h> +#include <nvif/mmu.h> +#include <nvif/vmm.h> -#include <drm/drmP.h> +#include <drm/drm_connector.h> +#include <drm/drm_device.h> +#include <drm/drm_drv.h> +#include <drm/drm_file.h> +#include <drm/drm_print.h> -#include <drm/ttm/ttm_bo_api.h> -#include <drm/ttm/ttm_bo_driver.h> +#include <drm/ttm/ttm_bo.h> #include <drm/ttm/ttm_placement.h> -#include <drm/ttm/ttm_memory.h> -#include <drm/ttm/ttm_module.h> -#include <drm/ttm/ttm_page_alloc.h> + +#include <drm/drm_audio_component.h> #include "uapi/drm/nouveau_drm.h" struct nouveau_channel; struct platform_device; -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - #include "nouveau_fence.h" #include "nouveau_bios.h" +#include "nouveau_sched.h" +#include "nouveau_vmm.h" +#include "nouveau_uvmm.h" struct nouveau_drm_tile { struct nouveau_fence *fence; @@ -74,11 +81,6 @@ enum nouveau_drm_object_route { NVDRM_OBJECT_ANY = NVIF_IOCTL_V0_OWNER_ANY, }; -enum nouveau_drm_notify_route { - NVDRM_NOTIFY_NVIF = 0, - NVDRM_NOTIFY_USIF -}; - enum nouveau_drm_handle { NVDRM_CHAN = 0xcccc0000, /* |= client chid */ NVDRM_NVSW = 0x55550000, @@ -86,34 +88,140 @@ enum nouveau_drm_handle { struct nouveau_cli { struct nvif_client base; - struct drm_device *dev; + struct nouveau_drm *drm; struct mutex mutex; struct nvif_device device; + struct nvif_mmu mmu; + struct nouveau_vmm vmm; + struct nouveau_vmm svm; + struct { + struct nouveau_uvmm *ptr; + bool disabled; + } uvmm; + + struct nouveau_sched *sched; + + const struct nvif_mclass *mem; - struct nvkm_vm *vm; /*XXX*/ struct list_head head; void *abi16; struct list_head objects; - struct list_head notifys; char name[32]; + + struct work_struct work; + struct list_head worker; + struct mutex lock; }; +struct nouveau_cli_work { + void (*func)(struct nouveau_cli_work *); + struct nouveau_cli *cli; + struct list_head head; + + struct dma_fence *fence; + struct dma_fence_cb cb; +}; + +static inline struct nouveau_uvmm * +nouveau_cli_uvmm(struct nouveau_cli *cli) +{ + return cli ? cli->uvmm.ptr : NULL; +} + +static inline struct nouveau_uvmm * +nouveau_cli_uvmm_locked(struct nouveau_cli *cli) +{ + struct nouveau_uvmm *uvmm; + + mutex_lock(&cli->mutex); + uvmm = nouveau_cli_uvmm(cli); + mutex_unlock(&cli->mutex); + + return uvmm; +} + +static inline struct nouveau_vmm * +nouveau_cli_vmm(struct nouveau_cli *cli) +{ + struct nouveau_uvmm *uvmm; + + uvmm = nouveau_cli_uvmm(cli); + if (uvmm) + return &uvmm->vmm; + + if (cli->svm.cli) + return &cli->svm; + + return &cli->vmm; +} + +static inline void +__nouveau_cli_disable_uvmm_noinit(struct nouveau_cli *cli) +{ + struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(cli); + + if (!uvmm) + cli->uvmm.disabled = true; +} + +static inline void +nouveau_cli_disable_uvmm_noinit(struct nouveau_cli *cli) +{ + mutex_lock(&cli->mutex); + __nouveau_cli_disable_uvmm_noinit(cli); + mutex_unlock(&cli->mutex); +} + +void nouveau_cli_work_queue(struct nouveau_cli *, struct dma_fence *, + struct nouveau_cli_work *); + static inline struct nouveau_cli * nouveau_cli(struct drm_file *fpriv) { return fpriv ? fpriv->driver_priv : NULL; } +static inline void +u_free(void *addr) +{ + kvfree(addr); +} + +static inline void * +u_memcpya(uint64_t user, unsigned int nmemb, unsigned int size) +{ + void __user *userptr = u64_to_user_ptr(user); + size_t bytes; + + if (unlikely(check_mul_overflow(nmemb, size, &bytes))) + return ERR_PTR(-EOVERFLOW); + return vmemdup_user(userptr, bytes); +} + #include <nvif/object.h> -#include <nvif/device.h> +#include <nvif/parent.h> struct nouveau_drm { + struct nvkm_device *nvkm; + struct nvif_parent parent; + struct mutex client_mutex; + struct nvif_client _client; + struct nvif_device device; + struct nvif_mmu mmu; + struct nouveau_cli client; struct drm_device *dev; struct list_head clients; + /** + * @clients_lock: Protects access to the @clients list of &struct nouveau_cli. + */ + struct mutex clients_lock; + + u8 old_pm_cap; + struct { struct agp_bridge_data *bridge; u32 base; @@ -123,16 +231,19 @@ struct nouveau_drm { /* TTM interface support */ struct { - struct drm_global_reference mem_global_ref; - struct ttm_bo_global_ref bo_global_ref; - struct ttm_bo_device bdev; + struct ttm_device bdev; atomic_t validate_sequence; int (*move)(struct nouveau_channel *, struct ttm_buffer_object *, - struct ttm_mem_reg *, struct ttm_mem_reg *); + struct ttm_resource *, struct ttm_resource *); struct nouveau_channel *chan; struct nvif_object copy; int mtrr; + int type_vram; + int type_host[2]; + int type_ncoh[2]; + struct mutex io_reserve_mutex; + struct list_head io_reserve_lru; } ttm; /* GEM interface support */ @@ -144,14 +255,24 @@ struct nouveau_drm { /* synchronisation */ void *fence; + /* Global channel management. */ + int chan_total; /* Number of channels across all runlists. */ + int chan_nr; /* 0 if per-runlist CHIDs. */ + int runl_nr; + struct { + int chan_nr; + int chan_id_base; + u64 context_base; + } *runl; + + /* Workqueue used for channel schedulers. */ + struct workqueue_struct *sched_wq; + /* context for accelerated drm-internal operations */ struct nouveau_channel *cechan; struct nouveau_channel *channel; struct nvkm_gpuobj *notify; - struct nouveau_fbdev *fbcon; - struct nvif_object nvsw; struct nvif_object ntfy; - struct nvif_notify flip; /* nv10-nv40 tiling regions */ struct { @@ -162,11 +283,10 @@ struct nouveau_drm { /* modesetting */ struct nvbios vbios; struct nouveau_display *display; - struct backlight_device *backlight; - struct list_head bl_connectors; + bool headless; struct work_struct hpd_work; - struct work_struct fbcon_work; - int fbcon_new_state; + spinlock_t hpd_lock; + u32 hpd_pending; #ifdef CONFIG_ACPI struct notifier_block acpi_nb; #endif @@ -178,11 +298,17 @@ struct nouveau_drm { /* led management */ struct nouveau_led *led; - /* display power reference */ - bool have_disp_power_ref; - struct dev_pm_domain vga_pm_domain; - struct pci_dev *hdmi_device; + + struct nouveau_svm *svm; + + struct nouveau_dmem *dmem; + + struct { + struct drm_audio_component *component; + struct mutex lock; + bool component_registered; + } audio; }; static inline struct nouveau_drm * @@ -191,6 +317,13 @@ nouveau_drm(struct drm_device *dev) return dev->dev_private; } +static inline bool +nouveau_drm_use_coherent_gpu_mapping(struct nouveau_drm *drm) +{ + struct nvif_mmu *mmu = &drm->client.mmu; + return !(mmu->type[drm->ttm.type_host[0]].type & NVIF_MEM_UNCACHED); +} + int nouveau_pmops_suspend(struct device *); int nouveau_pmops_resume(struct device *); bool nouveau_pmops_runtime(void); @@ -200,25 +333,73 @@ bool nouveau_pmops_runtime(void); struct drm_device * nouveau_platform_device_create(const struct nvkm_device_tegra_func *, struct platform_device *, struct nvkm_device **); -void nouveau_drm_device_remove(struct drm_device *dev); +void nouveau_drm_device_remove(struct nouveau_drm *); #define NV_PRINTK(l,c,f,a...) do { \ struct nouveau_cli *_cli = (c); \ - dev_##l(_cli->dev->dev, "%s: "f, _cli->name, ##a); \ + dev_##l(_cli->drm->dev->dev, "%s: "f, _cli->name, ##a); \ +} while(0) + +#define NV_PRINTK_(l,drm,f,a...) do { \ + dev_##l((drm)->nvkm->dev, "drm: "f, ##a); \ } while(0) -#define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a) -#define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a) -#define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a) -#define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a) +#define NV_FATAL(drm,f,a...) NV_PRINTK_(crit, (drm), f, ##a) +#define NV_ERROR(drm,f,a...) NV_PRINTK_(err, (drm), f, ##a) +#define NV_WARN(drm,f,a...) NV_PRINTK_(warn, (drm), f, ##a) +#define NV_INFO(drm,f,a...) NV_PRINTK_(info, (drm), f, ##a) + #define NV_DEBUG(drm,f,a...) do { \ - if (unlikely(drm_debug & DRM_UT_DRIVER)) \ - NV_PRINTK(info, &(drm)->client, f, ##a); \ + if (drm_debug_enabled(DRM_UT_DRIVER)) \ + NV_PRINTK_(info, (drm), f, ##a); \ } while(0) #define NV_ATOMIC(drm,f,a...) do { \ - if (unlikely(drm_debug & DRM_UT_ATOMIC)) \ - NV_PRINTK(info, &(drm)->client, f, ##a); \ + if (drm_debug_enabled(DRM_UT_ATOMIC)) \ + NV_PRINTK_(info, (drm), f, ##a); \ } while(0) +#define NV_PRINTK_ONCE(l,c,f,a...) NV_PRINTK(l##_once,c,f, ##a) + +#define NV_ERROR_ONCE(drm,f,a...) NV_PRINTK_ONCE(err, &(drm)->client, f, ##a) +#define NV_WARN_ONCE(drm,f,a...) NV_PRINTK_ONCE(warn, &(drm)->client, f, ##a) +#define NV_INFO_ONCE(drm,f,a...) NV_PRINTK_ONCE(info, &(drm)->client, f, ##a) + extern int nouveau_modeset; +/*XXX: Don't use these in new code. + * + * These accessors are used in a few places (mostly older code paths) + * to get direct access to NVKM structures, where a more well-defined + * interface doesn't exist. Outside of the current use, these should + * not be relied on, and instead be implemented as NVIF. + * + * This is especially important when considering GSP-RM, as a lot the + * modules don't exist, or are "stub" implementations that just allow + * the GSP-RM paths to be bootstrapped. + */ +#include <subdev/bios.h> +#include <subdev/fb.h> +#include <subdev/gpio.h> +#include <subdev/clk.h> +#include <subdev/i2c.h> +#include <subdev/timer.h> +#include <subdev/therm.h> + +static inline struct nvkm_device * +nvxx_device(struct nouveau_drm *drm) +{ + return drm->nvkm; +} + +#define nvxx_bios(a) nvxx_device(a)->bios +#define nvxx_fb(a) nvxx_device(a)->fb +#define nvxx_gpio(a) nvxx_device(a)->gpio +#define nvxx_clk(a) nvxx_device(a)->clk +#define nvxx_i2c(a) nvxx_device(a)->i2c +#define nvxx_iccsense(a) nvxx_device(a)->iccsense +#define nvxx_therm(a) nvxx_device(a)->therm +#define nvxx_volt(a) nvxx_device(a)->volt + +#include <engine/gr.h> + +#define nvxx_gr(a) nvxx_device(a)->gr #endif |
