aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_drm.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-07-19 18:17:34 -0400
committerBen Skeggs <bskeggs@redhat.com>2012-10-02 23:12:56 -0400
commitebb945a94bba2ce8dff7b0942ff2b3f2a52a0a69 (patch)
tree07cad59be501458e6ae1304b7c0352e322ac3387 /drivers/gpu/drm/nouveau/nouveau_drm.c
parentac1499d9573f4aadd1d2beac11fe23af8ce90c24 (diff)
drm/nouveau: port all engines to new engine module format
This is a HUGE commit, but it's not nearly as bad as it looks - any problems can be isolated to a particular chipset and engine combination. It was simply too difficult to port each one at a time, the compat layers are *already* ridiculous. Most of the changes here are simply to the glue, the process for each of the engine modules was to start with a standard skeleton and copy+paste the old code into the appropriate places, fixing up variable names etc as needed. v2: Marcin Slusarz <marcin.slusarz@gmail.com> - fix find/replace bug in license header v3: Ben Skeggs <bskeggs@redhat.com> - bump indirect pushbuf size to 8KiB, 4KiB barely enough for userspace and left no space for kernel's requirements during GEM pushbuf submission. - fix duplicate assignments noticed by clang v4: Marcin Slusarz <marcin.slusarz@gmail.com> - add sparse annotations to nv04_fifo_pause/nv04_fifo_start - use ioread32_native/iowrite32_native for fifo control registers v5: Ben Skeggs <bskeggs@redhat.com> - rebase on v3.6-rc4, modified to keep copy engine fix intact - nv10/fence: unmap fence bo before destroying - fixed fermi regression when using nvidia gr fuc - fixed typo in supported dma_mask checking Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_drm.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c211
1 files changed, 204 insertions, 7 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 3b4e65d5122b..92ecf50a39d3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -27,12 +27,20 @@
27 27
28#include <core/device.h> 28#include <core/device.h>
29#include <core/client.h> 29#include <core/client.h>
30#include <core/gpuobj.h>
30#include <core/class.h> 31#include <core/class.h>
31 32
32#include <subdev/device.h> 33#include <subdev/device.h>
34#include <subdev/vm.h>
33 35
34#include "nouveau_drm.h" 36#include "nouveau_drm.h"
37#include "nouveau_dma.h"
35#include "nouveau_agp.h" 38#include "nouveau_agp.h"
39#include "nouveau_abi16.h"
40#include "nouveau_fbcon.h"
41#include "nouveau_fence.h"
42
43#include "nouveau_ttm.h"
36 44
37int __devinit nouveau_pci_probe(struct pci_dev *, const struct pci_device_id *); 45int __devinit nouveau_pci_probe(struct pci_dev *, const struct pci_device_id *);
38void nouveau_pci_remove(struct pci_dev *); 46void nouveau_pci_remove(struct pci_dev *);
@@ -43,7 +51,6 @@ void __exit nouveau_exit(struct pci_driver *);
43 51
44int nouveau_load(struct drm_device *, unsigned long); 52int nouveau_load(struct drm_device *, unsigned long);
45int nouveau_unload(struct drm_device *); 53int nouveau_unload(struct drm_device *);
46void *nouveau_newpriv(struct drm_device *);
47 54
48MODULE_PARM_DESC(config, "option string to pass to driver core"); 55MODULE_PARM_DESC(config, "option string to pass to driver core");
49static char *nouveau_config; 56static char *nouveau_config;
@@ -53,6 +60,10 @@ MODULE_PARM_DESC(debug, "debug string to pass to driver core");
53static char *nouveau_debug; 60static char *nouveau_debug;
54module_param_named(debug, nouveau_debug, charp, 0400); 61module_param_named(debug, nouveau_debug, charp, 0400);
55 62
63MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");
64static int nouveau_noaccel = 0;
65module_param_named(noaccel, nouveau_noaccel, int, 0400);
66
56static u64 67static u64
57nouveau_name(struct pci_dev *pdev) 68nouveau_name(struct pci_dev *pdev)
58{ 69{
@@ -82,17 +93,112 @@ static void
82nouveau_cli_destroy(struct nouveau_cli *cli) 93nouveau_cli_destroy(struct nouveau_cli *cli)
83{ 94{
84 struct nouveau_object *client = nv_object(cli); 95 struct nouveau_object *client = nv_object(cli);
96 nouveau_vm_ref(NULL, &cli->base.vm, NULL);
85 nouveau_client_fini(&cli->base, false); 97 nouveau_client_fini(&cli->base, false);
86 atomic_set(&client->refcount, 1); 98 atomic_set(&client->refcount, 1);
87 nouveau_object_ref(NULL, &client); 99 nouveau_object_ref(NULL, &client);
88} 100}
89 101
102static void
103nouveau_accel_fini(struct nouveau_drm *drm)
104{
105 nouveau_gpuobj_ref(NULL, &drm->notify);
106 nouveau_channel_del(&drm->channel);
107 if (drm->fence)
108 nouveau_fence(drm)->dtor(drm);
109}
110
111static void
112nouveau_accel_init(struct nouveau_drm *drm)
113{
114 struct nouveau_device *device = nv_device(drm->device);
115 struct nouveau_object *object;
116 int ret;
117
118 if (nouveau_noaccel)
119 return;
120
121 /* initialise synchronisation routines */
122 if (device->card_type < NV_10) ret = nv04_fence_create(drm);
123 else if (device->chipset < 0x84) ret = nv10_fence_create(drm);
124 else if (device->card_type < NV_C0) ret = nv84_fence_create(drm);
125 else ret = nvc0_fence_create(drm);
126 if (ret) {
127 NV_ERROR(drm, "failed to initialise sync subsystem, %d\n", ret);
128 nouveau_accel_fini(drm);
129 return;
130 }
131
132 ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN,
133 NvDmaFB, NvDmaTT, &drm->channel);
134 if (ret) {
135 NV_ERROR(drm, "failed to create kernel channel, %d\n", ret);
136 nouveau_accel_fini(drm);
137 return;
138 }
139
140 if (device->card_type < NV_C0) {
141 ret = nouveau_gpuobj_new(drm->device, NULL, 32, 0, 0,
142 &drm->notify);
143 if (ret) {
144 NV_ERROR(drm, "failed to allocate notifier, %d\n", ret);
145 nouveau_accel_fini(drm);
146 return;
147 }
148
149 ret = nouveau_object_new(nv_object(drm),
150 drm->channel->handle, NvNotify0,
151 0x003d, &(struct nv_dma_class) {
152 .flags = NV_DMA_TARGET_VRAM |
153 NV_DMA_ACCESS_RDWR,
154 .start = drm->notify->addr,
155 .limit = drm->notify->addr + 31
156 }, sizeof(struct nv_dma_class),
157 &object);
158 if (ret) {
159 nouveau_accel_fini(drm);
160 return;
161 }
162 }
163
164
165 nouveau_bo_move_init(drm->channel);
166}
167
90static int __devinit 168static int __devinit
91nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent) 169nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent)
92{ 170{
93 struct nouveau_device *device; 171 struct nouveau_device *device;
172 struct apertures_struct *aper;
173 bool boot = false;
94 int ret; 174 int ret;
95 175
176 /* remove conflicting drivers (vesafb, efifb etc) */
177 aper = alloc_apertures(3);
178 if (!aper)
179 return -ENOMEM;
180
181 aper->ranges[0].base = pci_resource_start(pdev, 1);
182 aper->ranges[0].size = pci_resource_len(pdev, 1);
183 aper->count = 1;
184
185 if (pci_resource_len(pdev, 2)) {
186 aper->ranges[aper->count].base = pci_resource_start(pdev, 2);
187 aper->ranges[aper->count].size = pci_resource_len(pdev, 2);
188 aper->count++;
189 }
190
191 if (pci_resource_len(pdev, 3)) {
192 aper->ranges[aper->count].base = pci_resource_start(pdev, 3);
193 aper->ranges[aper->count].size = pci_resource_len(pdev, 3);
194 aper->count++;
195 }
196
197#ifdef CONFIG_X86
198 boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
199#endif
200 remove_conflicting_framebuffers(aper, "nouveaufb", boot);
201
96 ret = nouveau_device_create(pdev, nouveau_name(pdev), pci_name(pdev), 202 ret = nouveau_device_create(pdev, nouveau_name(pdev), pci_name(pdev),
97 nouveau_config, nouveau_debug, &device); 203 nouveau_config, nouveau_debug, &device);
98 if (ret) 204 if (ret)
@@ -102,7 +208,7 @@ nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent)
102 208
103 ret = nouveau_pci_probe(pdev, pent); 209 ret = nouveau_pci_probe(pdev, pent);
104 if (ret) { 210 if (ret) {
105 nouveau_device_destroy(&device); 211 nouveau_object_ref(NULL, (struct nouveau_object **)&device);
106 return ret; 212 return ret;
107 } 213 }
108 214
@@ -113,6 +219,7 @@ int
113nouveau_drm_load(struct drm_device *dev, unsigned long flags) 219nouveau_drm_load(struct drm_device *dev, unsigned long flags)
114{ 220{
115 struct pci_dev *pdev = dev->pdev; 221 struct pci_dev *pdev = dev->pdev;
222 struct nouveau_device *device;
116 struct nouveau_drm *drm; 223 struct nouveau_drm *drm;
117 int ret; 224 int ret;
118 225
@@ -122,6 +229,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
122 return ret; 229 return ret;
123 230
124 INIT_LIST_HEAD(&drm->clients); 231 INIT_LIST_HEAD(&drm->clients);
232 spin_lock_init(&drm->tile.lock);
125 drm->dev = dev; 233 drm->dev = dev;
126 234
127 /* make sure AGP controller is in a consistent state before we 235 /* make sure AGP controller is in a consistent state before we
@@ -142,7 +250,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
142 }, sizeof(struct nv_device_class), 250 }, sizeof(struct nv_device_class),
143 &drm->device); 251 &drm->device);
144 if (ret) 252 if (ret)
145 return ret; 253 goto fail_device;
146 254
147 nouveau_agp_reset(drm); 255 nouveau_agp_reset(drm);
148 nouveau_object_del(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE); 256 nouveau_object_del(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE);
@@ -158,15 +266,32 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
158 if (ret) 266 if (ret)
159 goto fail_device; 267 goto fail_device;
160 268
269 device = nv_device(drm->device);
270
161 /* initialise AGP */ 271 /* initialise AGP */
162 nouveau_agp_init(drm); 272 nouveau_agp_init(drm);
163 273
164 ret = nouveau_load(dev, flags); 274 if (device->card_type >= NV_50) {
275 ret = nouveau_vm_new(nv_device(drm->device), 0, (1ULL << 40),
276 0x1000, &drm->client.base.vm);
277 if (ret)
278 goto fail_device;
279 }
280
281 ret = nouveau_ttm_init(drm);
165 if (ret) 282 if (ret)
166 goto fail_device; 283 goto fail_device;
167 284
285 ret = nouveau_load(dev, flags);
286 if (ret)
287 goto fail_load;
288
289 nouveau_accel_init(drm);
290 nouveau_fbcon_init(dev);
168 return 0; 291 return 0;
169 292
293fail_load:
294 nouveau_ttm_fini(drm);
170fail_device: 295fail_device:
171 nouveau_cli_destroy(&drm->client); 296 nouveau_cli_destroy(&drm->client);
172 return ret; 297 return ret;
@@ -179,10 +304,14 @@ nouveau_drm_unload(struct drm_device *dev)
179 struct pci_dev *pdev = dev->pdev; 304 struct pci_dev *pdev = dev->pdev;
180 int ret; 305 int ret;
181 306
307 nouveau_fbcon_fini(dev);
308 nouveau_accel_fini(drm);
309
182 ret = nouveau_unload(dev); 310 ret = nouveau_unload(dev);
183 if (ret) 311 if (ret)
184 return ret; 312 return ret;
185 313
314 nouveau_ttm_fini(drm);
186 nouveau_agp_fini(drm); 315 nouveau_agp_fini(drm);
187 316
188 pci_set_drvdata(pdev, drm->client.base.device); 317 pci_set_drvdata(pdev, drm->client.base.device);
@@ -193,10 +322,11 @@ nouveau_drm_unload(struct drm_device *dev)
193static void 322static void
194nouveau_drm_remove(struct pci_dev *pdev) 323nouveau_drm_remove(struct pci_dev *pdev)
195{ 324{
196 struct nouveau_device *device; 325 struct nouveau_object *device;
197 nouveau_pci_remove(pdev); 326 nouveau_pci_remove(pdev);
198 device = pci_get_drvdata(pdev); 327 device = pci_get_drvdata(pdev);
199 nouveau_device_destroy(&device); 328 nouveau_object_ref(NULL, &device);
329 nouveau_object_debug();
200} 330}
201 331
202int 332int
@@ -211,10 +341,23 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
211 pm_state.event == PM_EVENT_PRETHAW) 341 pm_state.event == PM_EVENT_PRETHAW)
212 return 0; 342 return 0;
213 343
344 NV_INFO(drm, "suspending fbcon...\n");
345 nouveau_fbcon_set_suspend(dev, 1);
346
347 NV_INFO(drm, "suspending drm...\n");
214 ret = nouveau_pci_suspend(pdev, pm_state); 348 ret = nouveau_pci_suspend(pdev, pm_state);
215 if (ret) 349 if (ret)
216 return ret; 350 return ret;
217 351
352 NV_INFO(drm, "evicting buffers...\n");
353 ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
354
355 if (drm->fence && nouveau_fence(drm)->suspend) {
356 if (!nouveau_fence(drm)->suspend(drm))
357 return -ENOMEM;
358 }
359
360 NV_INFO(drm, "suspending client object trees...\n");
218 list_for_each_entry(cli, &drm->clients, head) { 361 list_for_each_entry(cli, &drm->clients, head) {
219 ret = nouveau_client_fini(&cli->base, true); 362 ret = nouveau_client_fini(&cli->base, true);
220 if (ret) 363 if (ret)
@@ -255,6 +398,7 @@ nouveau_drm_resume(struct pci_dev *pdev)
255 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) 398 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
256 return 0; 399 return 0;
257 400
401 NV_INFO(drm, "re-enabling device...\n");
258 pci_set_power_state(pdev, PCI_D0); 402 pci_set_power_state(pdev, PCI_D0);
259 pci_restore_state(pdev); 403 pci_restore_state(pdev);
260 ret = pci_enable_device(pdev); 404 ret = pci_enable_device(pdev);
@@ -264,17 +408,70 @@ nouveau_drm_resume(struct pci_dev *pdev)
264 408
265 nouveau_agp_reset(drm); 409 nouveau_agp_reset(drm);
266 410
411 NV_INFO(drm, "resuming client object trees...\n");
267 nouveau_client_init(&drm->client.base); 412 nouveau_client_init(&drm->client.base);
413 nouveau_agp_init(drm);
268 414
269 list_for_each_entry(cli, &drm->clients, head) { 415 list_for_each_entry(cli, &drm->clients, head) {
270 nouveau_client_init(&cli->base); 416 nouveau_client_init(&cli->base);
271 } 417 }
272 418
273 nouveau_agp_init(drm); 419 if (drm->fence && nouveau_fence(drm)->resume)
420 nouveau_fence(drm)->resume(drm);
274 421
275 return nouveau_pci_resume(pdev); 422 return nouveau_pci_resume(pdev);
276} 423}
277 424
425int
426nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
427{
428 struct pci_dev *pdev = dev->pdev;
429 struct nouveau_drm *drm = nouveau_drm(dev);
430 struct nouveau_cli *cli;
431 int ret;
432
433 ret = nouveau_cli_create(pdev, fpriv->pid, sizeof(*cli), (void **)&cli);
434 if (ret)
435 return ret;
436
437 if (nv_device(drm->device)->card_type >= NV_50) {
438 ret = nouveau_vm_new(nv_device(drm->device), 0, (1ULL << 40),
439 0x1000, &cli->base.vm);
440 if (ret) {
441 nouveau_cli_destroy(cli);
442 return ret;
443 }
444 }
445
446 fpriv->driver_priv = cli;
447
448 mutex_lock(&drm->client.mutex);
449 list_add(&cli->head, &drm->clients);
450 mutex_unlock(&drm->client.mutex);
451 return 0;
452}
453
454void
455nouveau_drm_preclose(struct drm_device *dev, struct drm_file *fpriv)
456{
457 struct nouveau_cli *cli = nouveau_cli(fpriv);
458 struct nouveau_drm *drm = nouveau_drm(dev);
459
460 if (cli->abi16)
461 nouveau_abi16_fini(cli->abi16);
462
463 mutex_lock(&drm->client.mutex);
464 list_del(&cli->head);
465 mutex_unlock(&drm->client.mutex);
466}
467
468void
469nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
470{
471 struct nouveau_cli *cli = nouveau_cli(fpriv);
472 nouveau_cli_destroy(cli);
473}
474
278static struct pci_device_id 475static struct pci_device_id
279nouveau_drm_pci_table[] = { 476nouveau_drm_pci_table[] = {
280 { 477 {