1 | /* SPDX-License-Identifier: MIT */ |
2 | #ifndef __NOUVEAU_DRV_H__ |
3 | #define __NOUVEAU_DRV_H__ |
4 | |
5 | #define DRIVER_AUTHOR "Nouveau Project" |
6 | #define DRIVER_EMAIL "nouveau@lists.freedesktop.org" |
7 | |
8 | #define DRIVER_NAME "nouveau" |
9 | #define DRIVER_DESC "nVidia Riva/TNT/GeForce/Quadro/Tesla/Tegra K1+" |
10 | #define DRIVER_DATE "20120801" |
11 | |
12 | #define DRIVER_MAJOR 1 |
13 | #define DRIVER_MINOR 4 |
14 | #define DRIVER_PATCHLEVEL 0 |
15 | |
16 | /* |
17 | * 1.1.1: |
18 | * - added support for tiled system memory buffer objects |
19 | * - added support for NOUVEAU_GETPARAM_GRAPH_UNITS on [nvc0,nve0]. |
20 | * - added support for compressed memory storage types on [nvc0,nve0]. |
21 | * - added support for software methods 0x600,0x644,0x6ac on nvc0 |
22 | * to control registers on the MPs to enable performance counters, |
23 | * and to control the warp error enable mask (OpenGL requires out of |
24 | * bounds access to local memory to be silently ignored / return 0). |
25 | * 1.1.2: |
26 | * - fixes multiple bugs in flip completion events and timestamping |
27 | * 1.2.0: |
28 | * - object api exposed to userspace |
29 | * - fermi,kepler,maxwell zbc |
30 | * 1.2.1: |
31 | * - allow concurrent access to bo's mapped read/write. |
32 | * 1.2.2: |
33 | * - add NOUVEAU_GEM_DOMAIN_COHERENT flag |
34 | * 1.3.0: |
35 | * - NVIF ABI modified, safe because only (current) users are test |
36 | * programs that get directly linked with NVKM. |
37 | * 1.3.1: |
38 | * - implemented limited ABI16/NVIF interop |
39 | */ |
40 | |
41 | #include <linux/notifier.h> |
42 | |
43 | #include <nvif/client.h> |
44 | #include <nvif/device.h> |
45 | #include <nvif/ioctl.h> |
46 | #include <nvif/mmu.h> |
47 | #include <nvif/vmm.h> |
48 | |
49 | #include <drm/drm_connector.h> |
50 | #include <drm/drm_device.h> |
51 | #include <drm/drm_drv.h> |
52 | #include <drm/drm_file.h> |
53 | |
54 | #include <drm/ttm/ttm_bo.h> |
55 | #include <drm/ttm/ttm_placement.h> |
56 | |
57 | #include <drm/drm_audio_component.h> |
58 | |
59 | #include "uapi/drm/nouveau_drm.h" |
60 | |
61 | struct nouveau_channel; |
62 | struct platform_device; |
63 | |
64 | #include "nouveau_fence.h" |
65 | #include "nouveau_bios.h" |
66 | #include "nouveau_sched.h" |
67 | #include "nouveau_vmm.h" |
68 | #include "nouveau_uvmm.h" |
69 | |
70 | struct nouveau_drm_tile { |
71 | struct nouveau_fence *fence; |
72 | bool used; |
73 | }; |
74 | |
75 | enum nouveau_drm_object_route { |
76 | NVDRM_OBJECT_NVIF = NVIF_IOCTL_V0_OWNER_NVIF, |
77 | NVDRM_OBJECT_USIF, |
78 | NVDRM_OBJECT_ABI16, |
79 | NVDRM_OBJECT_ANY = NVIF_IOCTL_V0_OWNER_ANY, |
80 | }; |
81 | |
82 | enum nouveau_drm_handle { |
83 | NVDRM_CHAN = 0xcccc0000, /* |= client chid */ |
84 | NVDRM_NVSW = 0x55550000, |
85 | }; |
86 | |
87 | struct nouveau_cli { |
88 | struct nvif_client base; |
89 | struct nouveau_drm *drm; |
90 | struct mutex mutex; |
91 | |
92 | struct nvif_device device; |
93 | struct nvif_mmu mmu; |
94 | struct nouveau_vmm vmm; |
95 | struct nouveau_vmm svm; |
96 | struct nouveau_uvmm uvmm; |
97 | |
98 | struct nouveau_sched_entity sched_entity; |
99 | |
100 | const struct nvif_mclass *mem; |
101 | |
102 | struct list_head head; |
103 | void *abi16; |
104 | struct list_head objects; |
105 | char name[32]; |
106 | |
107 | struct work_struct work; |
108 | struct list_head worker; |
109 | struct mutex lock; |
110 | }; |
111 | |
112 | struct nouveau_cli_work { |
113 | void (*func)(struct nouveau_cli_work *); |
114 | struct nouveau_cli *cli; |
115 | struct list_head head; |
116 | |
117 | struct dma_fence *fence; |
118 | struct dma_fence_cb cb; |
119 | }; |
120 | |
121 | static inline struct nouveau_uvmm * |
122 | nouveau_cli_uvmm(struct nouveau_cli *cli) |
123 | { |
124 | if (!cli || !cli->uvmm.vmm.cli) |
125 | return NULL; |
126 | |
127 | return &cli->uvmm; |
128 | } |
129 | |
130 | static inline struct nouveau_uvmm * |
131 | nouveau_cli_uvmm_locked(struct nouveau_cli *cli) |
132 | { |
133 | struct nouveau_uvmm *uvmm; |
134 | |
135 | mutex_lock(&cli->mutex); |
136 | uvmm = nouveau_cli_uvmm(cli); |
137 | mutex_unlock(lock: &cli->mutex); |
138 | |
139 | return uvmm; |
140 | } |
141 | |
142 | static inline struct nouveau_vmm * |
143 | nouveau_cli_vmm(struct nouveau_cli *cli) |
144 | { |
145 | struct nouveau_uvmm *uvmm; |
146 | |
147 | uvmm = nouveau_cli_uvmm(cli); |
148 | if (uvmm) |
149 | return &uvmm->vmm; |
150 | |
151 | if (cli->svm.cli) |
152 | return &cli->svm; |
153 | |
154 | return &cli->vmm; |
155 | } |
156 | |
157 | static inline void |
158 | __nouveau_cli_disable_uvmm_noinit(struct nouveau_cli *cli) |
159 | { |
160 | struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(cli); |
161 | |
162 | if (!uvmm) |
163 | cli->uvmm.disabled = true; |
164 | } |
165 | |
166 | static inline void |
167 | nouveau_cli_disable_uvmm_noinit(struct nouveau_cli *cli) |
168 | { |
169 | mutex_lock(&cli->mutex); |
170 | __nouveau_cli_disable_uvmm_noinit(cli); |
171 | mutex_unlock(lock: &cli->mutex); |
172 | } |
173 | |
174 | void nouveau_cli_work_queue(struct nouveau_cli *, struct dma_fence *, |
175 | struct nouveau_cli_work *); |
176 | |
177 | static inline struct nouveau_cli * |
178 | nouveau_cli(struct drm_file *fpriv) |
179 | { |
180 | return fpriv ? fpriv->driver_priv : NULL; |
181 | } |
182 | |
183 | static inline void |
184 | u_free(void *addr) |
185 | { |
186 | kvfree(addr); |
187 | } |
188 | |
189 | static inline void * |
190 | u_memcpya(uint64_t user, unsigned int nmemb, unsigned int size) |
191 | { |
192 | void __user *userptr = u64_to_user_ptr(user); |
193 | size_t bytes; |
194 | |
195 | if (unlikely(check_mul_overflow(nmemb, size, &bytes))) |
196 | return ERR_PTR(error: -EOVERFLOW); |
197 | return vmemdup_user(userptr, bytes); |
198 | } |
199 | |
200 | #include <nvif/object.h> |
201 | #include <nvif/parent.h> |
202 | |
203 | struct nouveau_drm { |
204 | struct nvif_parent parent; |
205 | struct nouveau_cli master; |
206 | struct nouveau_cli client; |
207 | struct drm_device *dev; |
208 | |
209 | struct list_head clients; |
210 | |
211 | /** |
212 | * @clients_lock: Protects access to the @clients list of &struct nouveau_cli. |
213 | */ |
214 | struct mutex clients_lock; |
215 | |
216 | u8 old_pm_cap; |
217 | |
218 | struct { |
219 | struct agp_bridge_data *bridge; |
220 | u32 base; |
221 | u32 size; |
222 | bool cma; |
223 | } agp; |
224 | |
225 | /* TTM interface support */ |
226 | struct { |
227 | struct ttm_device bdev; |
228 | atomic_t validate_sequence; |
229 | int (*move)(struct nouveau_channel *, |
230 | struct ttm_buffer_object *, |
231 | struct ttm_resource *, struct ttm_resource *); |
232 | struct nouveau_channel *chan; |
233 | struct nvif_object copy; |
234 | int mtrr; |
235 | int type_vram; |
236 | int type_host[2]; |
237 | int type_ncoh[2]; |
238 | struct mutex io_reserve_mutex; |
239 | struct list_head io_reserve_lru; |
240 | } ttm; |
241 | |
242 | /* GEM interface support */ |
243 | struct { |
244 | u64 vram_available; |
245 | u64 gart_available; |
246 | } gem; |
247 | |
248 | /* synchronisation */ |
249 | void *fence; |
250 | |
251 | /* Global channel management. */ |
252 | int chan_total; /* Number of channels across all runlists. */ |
253 | int chan_nr; /* 0 if per-runlist CHIDs. */ |
254 | int runl_nr; |
255 | struct { |
256 | int chan_nr; |
257 | int chan_id_base; |
258 | u64 context_base; |
259 | } *runl; |
260 | |
261 | /* context for accelerated drm-internal operations */ |
262 | struct nouveau_channel *cechan; |
263 | struct nouveau_channel *channel; |
264 | struct nvkm_gpuobj *notify; |
265 | struct nvif_object ntfy; |
266 | |
267 | /* nv10-nv40 tiling regions */ |
268 | struct { |
269 | struct nouveau_drm_tile reg[15]; |
270 | spinlock_t lock; |
271 | } tile; |
272 | |
273 | /* modesetting */ |
274 | struct nvbios vbios; |
275 | struct nouveau_display *display; |
276 | struct work_struct hpd_work; |
277 | spinlock_t hpd_lock; |
278 | u32 hpd_pending; |
279 | #ifdef CONFIG_ACPI |
280 | struct notifier_block acpi_nb; |
281 | #endif |
282 | |
283 | /* power management */ |
284 | struct nouveau_hwmon *hwmon; |
285 | struct nouveau_debugfs *debugfs; |
286 | |
287 | /* led management */ |
288 | struct nouveau_led *led; |
289 | |
290 | struct dev_pm_domain vga_pm_domain; |
291 | |
292 | struct nouveau_svm *svm; |
293 | |
294 | struct nouveau_dmem *dmem; |
295 | |
296 | struct { |
297 | struct drm_audio_component *component; |
298 | struct mutex lock; |
299 | bool component_registered; |
300 | } audio; |
301 | |
302 | struct drm_gpu_scheduler sched; |
303 | struct workqueue_struct *sched_wq; |
304 | |
305 | }; |
306 | |
307 | static inline struct nouveau_drm * |
308 | nouveau_drm(struct drm_device *dev) |
309 | { |
310 | return dev->dev_private; |
311 | } |
312 | |
313 | static inline bool |
314 | nouveau_drm_use_coherent_gpu_mapping(struct nouveau_drm *drm) |
315 | { |
316 | struct nvif_mmu *mmu = &drm->client.mmu; |
317 | return !(mmu->type[drm->ttm.type_host[0]].type & NVIF_MEM_UNCACHED); |
318 | } |
319 | |
320 | int nouveau_pmops_suspend(struct device *); |
321 | int nouveau_pmops_resume(struct device *); |
322 | bool nouveau_pmops_runtime(void); |
323 | |
324 | #include <nvkm/core/tegra.h> |
325 | |
326 | struct drm_device * |
327 | nouveau_platform_device_create(const struct nvkm_device_tegra_func *, |
328 | struct platform_device *, struct nvkm_device **); |
329 | void nouveau_drm_device_remove(struct drm_device *dev); |
330 | |
331 | #define NV_PRINTK(l,c,f,a...) do { \ |
332 | struct nouveau_cli *_cli = (c); \ |
333 | dev_##l(_cli->drm->dev->dev, "%s: "f, _cli->name, ##a); \ |
334 | } while(0) |
335 | |
336 | #define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a) |
337 | #define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a) |
338 | #define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a) |
339 | #define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a) |
340 | |
341 | #define NV_DEBUG(drm,f,a...) do { \ |
342 | if (drm_debug_enabled(DRM_UT_DRIVER)) \ |
343 | NV_PRINTK(info, &(drm)->client, f, ##a); \ |
344 | } while(0) |
345 | #define NV_ATOMIC(drm,f,a...) do { \ |
346 | if (drm_debug_enabled(DRM_UT_ATOMIC)) \ |
347 | NV_PRINTK(info, &(drm)->client, f, ##a); \ |
348 | } while(0) |
349 | |
350 | #define NV_PRINTK_ONCE(l,c,f,a...) NV_PRINTK(l##_once,c,f, ##a) |
351 | |
352 | #define NV_ERROR_ONCE(drm,f,a...) NV_PRINTK_ONCE(err, &(drm)->client, f, ##a) |
353 | #define NV_WARN_ONCE(drm,f,a...) NV_PRINTK_ONCE(warn, &(drm)->client, f, ##a) |
354 | #define NV_INFO_ONCE(drm,f,a...) NV_PRINTK_ONCE(info, &(drm)->client, f, ##a) |
355 | |
356 | extern int nouveau_modeset; |
357 | |
358 | #endif |
359 | |