diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_drm.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drm.c | 307 |
1 files changed, 183 insertions, 124 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index c9428c943afb..250a5e88c751 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -27,21 +27,14 @@ | |||
27 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
29 | #include <linux/vga_switcheroo.h> | 29 | #include <linux/vga_switcheroo.h> |
30 | |||
30 | #include "drmP.h" | 31 | #include "drmP.h" |
31 | #include "drm_crtc_helper.h" | 32 | #include "drm_crtc_helper.h" |
33 | |||
32 | #include <core/device.h> | 34 | #include <core/device.h> |
33 | #include <core/client.h> | ||
34 | #include <core/gpuobj.h> | 35 | #include <core/gpuobj.h> |
35 | #include <core/class.h> | ||
36 | #include <core/option.h> | 36 | #include <core/option.h> |
37 | 37 | ||
38 | #include <engine/device.h> | ||
39 | #include <engine/disp.h> | ||
40 | #include <engine/fifo.h> | ||
41 | #include <engine/software.h> | ||
42 | |||
43 | #include <subdev/vm.h> | ||
44 | |||
45 | #include "nouveau_drm.h" | 38 | #include "nouveau_drm.h" |
46 | #include "nouveau_dma.h" | 39 | #include "nouveau_dma.h" |
47 | #include "nouveau_ttm.h" | 40 | #include "nouveau_ttm.h" |
@@ -57,6 +50,7 @@ | |||
57 | #include "nouveau_fbcon.h" | 50 | #include "nouveau_fbcon.h" |
58 | #include "nouveau_fence.h" | 51 | #include "nouveau_fence.h" |
59 | #include "nouveau_debugfs.h" | 52 | #include "nouveau_debugfs.h" |
53 | #include "nouveau_usif.h" | ||
60 | 54 | ||
61 | MODULE_PARM_DESC(config, "option string to pass to driver core"); | 55 | MODULE_PARM_DESC(config, "option string to pass to driver core"); |
62 | static char *nouveau_config; | 56 | static char *nouveau_config; |
@@ -109,40 +103,37 @@ static int | |||
109 | nouveau_cli_create(u64 name, const char *sname, | 103 | nouveau_cli_create(u64 name, const char *sname, |
110 | int size, void **pcli) | 104 | int size, void **pcli) |
111 | { | 105 | { |
112 | struct nouveau_cli *cli; | 106 | struct nouveau_cli *cli = *pcli = kzalloc(size, GFP_KERNEL); |
113 | int ret; | 107 | if (cli) { |
114 | 108 | int ret = nvif_client_init(NULL, NULL, sname, name, | |
115 | *pcli = NULL; | 109 | nouveau_config, nouveau_debug, |
116 | ret = nouveau_client_create_(sname, name, nouveau_config, | 110 | &cli->base); |
117 | nouveau_debug, size, pcli); | 111 | if (ret == 0) { |
118 | cli = *pcli; | 112 | mutex_init(&cli->mutex); |
119 | if (ret) { | 113 | usif_client_init(cli); |
120 | if (cli) | 114 | } |
121 | nouveau_client_destroy(&cli->base); | ||
122 | *pcli = NULL; | ||
123 | return ret; | 115 | return ret; |
124 | } | 116 | } |
125 | 117 | return -ENOMEM; | |
126 | mutex_init(&cli->mutex); | ||
127 | return 0; | ||
128 | } | 118 | } |
129 | 119 | ||
130 | static void | 120 | static void |
131 | nouveau_cli_destroy(struct nouveau_cli *cli) | 121 | nouveau_cli_destroy(struct nouveau_cli *cli) |
132 | { | 122 | { |
133 | struct nouveau_object *client = nv_object(cli); | 123 | nouveau_vm_ref(NULL, &nvkm_client(&cli->base)->vm, NULL); |
134 | nouveau_vm_ref(NULL, &cli->base.vm, NULL); | 124 | nvif_client_fini(&cli->base); |
135 | nouveau_client_fini(&cli->base, false); | 125 | usif_client_fini(cli); |
136 | atomic_set(&client->refcount, 1); | ||
137 | nouveau_object_ref(NULL, &client); | ||
138 | } | 126 | } |
139 | 127 | ||
140 | static void | 128 | static void |
141 | nouveau_accel_fini(struct nouveau_drm *drm) | 129 | nouveau_accel_fini(struct nouveau_drm *drm) |
142 | { | 130 | { |
143 | nouveau_gpuobj_ref(NULL, &drm->notify); | ||
144 | nouveau_channel_del(&drm->channel); | 131 | nouveau_channel_del(&drm->channel); |
132 | nvif_object_fini(&drm->ntfy); | ||
133 | nouveau_gpuobj_ref(NULL, &drm->notify); | ||
134 | nvif_object_fini(&drm->nvsw); | ||
145 | nouveau_channel_del(&drm->cechan); | 135 | nouveau_channel_del(&drm->cechan); |
136 | nvif_object_fini(&drm->ttm.copy); | ||
146 | if (drm->fence) | 137 | if (drm->fence) |
147 | nouveau_fence(drm)->dtor(drm); | 138 | nouveau_fence(drm)->dtor(drm); |
148 | } | 139 | } |
@@ -150,46 +141,71 @@ nouveau_accel_fini(struct nouveau_drm *drm) | |||
150 | static void | 141 | static void |
151 | nouveau_accel_init(struct nouveau_drm *drm) | 142 | nouveau_accel_init(struct nouveau_drm *drm) |
152 | { | 143 | { |
153 | struct nouveau_device *device = nv_device(drm->device); | 144 | struct nvif_device *device = &drm->device; |
154 | struct nouveau_object *object; | ||
155 | u32 arg0, arg1; | 145 | u32 arg0, arg1; |
156 | int ret; | 146 | u32 sclass[16]; |
147 | int ret, i; | ||
157 | 148 | ||
158 | if (nouveau_noaccel || !nouveau_fifo(device) /*XXX*/) | 149 | if (nouveau_noaccel) |
159 | return; | 150 | return; |
160 | 151 | ||
161 | /* initialise synchronisation routines */ | 152 | /* initialise synchronisation routines */ |
162 | if (device->card_type < NV_10) ret = nv04_fence_create(drm); | 153 | /*XXX: this is crap, but the fence/channel stuff is a little |
163 | else if (device->card_type < NV_11 || | 154 | * backwards in some places. this will be fixed. |
164 | device->chipset < 0x17) ret = nv10_fence_create(drm); | 155 | */ |
165 | else if (device->card_type < NV_50) ret = nv17_fence_create(drm); | 156 | ret = nvif_object_sclass(&device->base, sclass, ARRAY_SIZE(sclass)); |
166 | else if (device->chipset < 0x84) ret = nv50_fence_create(drm); | 157 | if (ret < 0) |
167 | else if (device->card_type < NV_C0) ret = nv84_fence_create(drm); | 158 | return; |
168 | else ret = nvc0_fence_create(drm); | 159 | |
160 | for (ret = -ENOSYS, i = 0; ret && i < ARRAY_SIZE(sclass); i++) { | ||
161 | switch (sclass[i]) { | ||
162 | case NV03_CHANNEL_DMA: | ||
163 | ret = nv04_fence_create(drm); | ||
164 | break; | ||
165 | case NV10_CHANNEL_DMA: | ||
166 | ret = nv10_fence_create(drm); | ||
167 | break; | ||
168 | case NV17_CHANNEL_DMA: | ||
169 | case NV40_CHANNEL_DMA: | ||
170 | ret = nv17_fence_create(drm); | ||
171 | break; | ||
172 | case NV50_CHANNEL_GPFIFO: | ||
173 | ret = nv50_fence_create(drm); | ||
174 | break; | ||
175 | case G82_CHANNEL_GPFIFO: | ||
176 | ret = nv84_fence_create(drm); | ||
177 | break; | ||
178 | case FERMI_CHANNEL_GPFIFO: | ||
179 | case KEPLER_CHANNEL_GPFIFO_A: | ||
180 | ret = nvc0_fence_create(drm); | ||
181 | break; | ||
182 | default: | ||
183 | break; | ||
184 | } | ||
185 | } | ||
186 | |||
169 | if (ret) { | 187 | if (ret) { |
170 | NV_ERROR(drm, "failed to initialise sync subsystem, %d\n", ret); | 188 | NV_ERROR(drm, "failed to initialise sync subsystem, %d\n", ret); |
171 | nouveau_accel_fini(drm); | 189 | nouveau_accel_fini(drm); |
172 | return; | 190 | return; |
173 | } | 191 | } |
174 | 192 | ||
175 | if (device->card_type >= NV_E0) { | 193 | if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { |
176 | ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, | 194 | ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1, |
177 | NVDRM_CHAN + 1, | 195 | KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0| |
178 | NVE0_CHANNEL_IND_ENGINE_CE0 | | 196 | KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1, |
179 | NVE0_CHANNEL_IND_ENGINE_CE1, 0, | 197 | 0, &drm->cechan); |
180 | &drm->cechan); | ||
181 | if (ret) | 198 | if (ret) |
182 | NV_ERROR(drm, "failed to create ce channel, %d\n", ret); | 199 | NV_ERROR(drm, "failed to create ce channel, %d\n", ret); |
183 | 200 | ||
184 | arg0 = NVE0_CHANNEL_IND_ENGINE_GR; | 201 | arg0 = KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR; |
185 | arg1 = 1; | 202 | arg1 = 1; |
186 | } else | 203 | } else |
187 | if (device->chipset >= 0xa3 && | 204 | if (device->info.chipset >= 0xa3 && |
188 | device->chipset != 0xaa && | 205 | device->info.chipset != 0xaa && |
189 | device->chipset != 0xac) { | 206 | device->info.chipset != 0xac) { |
190 | ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, | 207 | ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1, |
191 | NVDRM_CHAN + 1, NvDmaFB, NvDmaTT, | 208 | NvDmaFB, NvDmaTT, &drm->cechan); |
192 | &drm->cechan); | ||
193 | if (ret) | 209 | if (ret) |
194 | NV_ERROR(drm, "failed to create ce channel, %d\n", ret); | 210 | NV_ERROR(drm, "failed to create ce channel, %d\n", ret); |
195 | 211 | ||
@@ -200,30 +216,30 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
200 | arg1 = NvDmaTT; | 216 | arg1 = NvDmaTT; |
201 | } | 217 | } |
202 | 218 | ||
203 | ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN, | 219 | ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN, arg0, arg1, |
204 | arg0, arg1, &drm->channel); | 220 | &drm->channel); |
205 | if (ret) { | 221 | if (ret) { |
206 | NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); | 222 | NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); |
207 | nouveau_accel_fini(drm); | 223 | nouveau_accel_fini(drm); |
208 | return; | 224 | return; |
209 | } | 225 | } |
210 | 226 | ||
211 | ret = nouveau_object_new(nv_object(drm), NVDRM_CHAN, NVDRM_NVSW, | 227 | ret = nvif_object_init(drm->channel->object, NULL, NVDRM_NVSW, |
212 | nouveau_abi16_swclass(drm), NULL, 0, &object); | 228 | nouveau_abi16_swclass(drm), NULL, 0, &drm->nvsw); |
213 | if (ret == 0) { | 229 | if (ret == 0) { |
214 | struct nouveau_software_chan *swch = (void *)object->parent; | 230 | struct nouveau_software_chan *swch; |
215 | ret = RING_SPACE(drm->channel, 2); | 231 | ret = RING_SPACE(drm->channel, 2); |
216 | if (ret == 0) { | 232 | if (ret == 0) { |
217 | if (device->card_type < NV_C0) { | 233 | if (device->info.family < NV_DEVICE_INFO_V0_FERMI) { |
218 | BEGIN_NV04(drm->channel, NvSubSw, 0, 1); | 234 | BEGIN_NV04(drm->channel, NvSubSw, 0, 1); |
219 | OUT_RING (drm->channel, NVDRM_NVSW); | 235 | OUT_RING (drm->channel, NVDRM_NVSW); |
220 | } else | 236 | } else |
221 | if (device->card_type < NV_E0) { | 237 | if (device->info.family < NV_DEVICE_INFO_V0_KEPLER) { |
222 | BEGIN_NVC0(drm->channel, FermiSw, 0, 1); | 238 | BEGIN_NVC0(drm->channel, FermiSw, 0, 1); |
223 | OUT_RING (drm->channel, 0x001f0000); | 239 | OUT_RING (drm->channel, 0x001f0000); |
224 | } | 240 | } |
225 | } | 241 | } |
226 | swch = (void *)object->parent; | 242 | swch = (void *)nvkm_object(&drm->nvsw)->parent; |
227 | swch->flip = nouveau_flip_complete; | 243 | swch->flip = nouveau_flip_complete; |
228 | swch->flip_data = drm->channel; | 244 | swch->flip_data = drm->channel; |
229 | } | 245 | } |
@@ -234,24 +250,24 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
234 | return; | 250 | return; |
235 | } | 251 | } |
236 | 252 | ||
237 | if (device->card_type < NV_C0) { | 253 | if (device->info.family < NV_DEVICE_INFO_V0_FERMI) { |
238 | ret = nouveau_gpuobj_new(drm->device, NULL, 32, 0, 0, | 254 | ret = nouveau_gpuobj_new(nvkm_object(&drm->device), NULL, 32, |
239 | &drm->notify); | 255 | 0, 0, &drm->notify); |
240 | if (ret) { | 256 | if (ret) { |
241 | NV_ERROR(drm, "failed to allocate notifier, %d\n", ret); | 257 | NV_ERROR(drm, "failed to allocate notifier, %d\n", ret); |
242 | nouveau_accel_fini(drm); | 258 | nouveau_accel_fini(drm); |
243 | return; | 259 | return; |
244 | } | 260 | } |
245 | 261 | ||
246 | ret = nouveau_object_new(nv_object(drm), | 262 | ret = nvif_object_init(drm->channel->object, NULL, NvNotify0, |
247 | drm->channel->handle, NvNotify0, | 263 | NV_DMA_IN_MEMORY, |
248 | 0x003d, &(struct nv_dma_class) { | 264 | &(struct nv_dma_v0) { |
249 | .flags = NV_DMA_TARGET_VRAM | | 265 | .target = NV_DMA_V0_TARGET_VRAM, |
250 | NV_DMA_ACCESS_RDWR, | 266 | .access = NV_DMA_V0_ACCESS_RDWR, |
251 | .start = drm->notify->addr, | 267 | .start = drm->notify->addr, |
252 | .limit = drm->notify->addr + 31 | 268 | .limit = drm->notify->addr + 31 |
253 | }, sizeof(struct nv_dma_class), | 269 | }, sizeof(struct nv_dma_v0), |
254 | &object); | 270 | &drm->ntfy); |
255 | if (ret) { | 271 | if (ret) { |
256 | nouveau_accel_fini(drm); | 272 | nouveau_accel_fini(drm); |
257 | return; | 273 | return; |
@@ -294,7 +310,8 @@ static int nouveau_drm_probe(struct pci_dev *pdev, | |||
294 | #ifdef CONFIG_X86 | 310 | #ifdef CONFIG_X86 |
295 | boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; | 311 | boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; |
296 | #endif | 312 | #endif |
297 | remove_conflicting_framebuffers(aper, "nouveaufb", boot); | 313 | if (nouveau_modeset != 2) |
314 | remove_conflicting_framebuffers(aper, "nouveaufb", boot); | ||
298 | kfree(aper); | 315 | kfree(aper); |
299 | 316 | ||
300 | ret = nouveau_device_create(pdev, NOUVEAU_BUS_PCI, | 317 | ret = nouveau_device_create(pdev, NOUVEAU_BUS_PCI, |
@@ -348,7 +365,6 @@ static int | |||
348 | nouveau_drm_load(struct drm_device *dev, unsigned long flags) | 365 | nouveau_drm_load(struct drm_device *dev, unsigned long flags) |
349 | { | 366 | { |
350 | struct pci_dev *pdev = dev->pdev; | 367 | struct pci_dev *pdev = dev->pdev; |
351 | struct nouveau_device *device; | ||
352 | struct nouveau_drm *drm; | 368 | struct nouveau_drm *drm; |
353 | int ret; | 369 | int ret; |
354 | 370 | ||
@@ -359,7 +375,8 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) | |||
359 | 375 | ||
360 | dev->dev_private = drm; | 376 | dev->dev_private = drm; |
361 | drm->dev = dev; | 377 | drm->dev = dev; |
362 | nouveau_client(drm)->debug = nouveau_dbgopt(nouveau_debug, "DRM"); | 378 | nvkm_client(&drm->client.base)->debug = |
379 | nouveau_dbgopt(nouveau_debug, "DRM"); | ||
363 | 380 | ||
364 | INIT_LIST_HEAD(&drm->clients); | 381 | INIT_LIST_HEAD(&drm->clients); |
365 | spin_lock_init(&drm->tile.lock); | 382 | spin_lock_init(&drm->tile.lock); |
@@ -370,33 +387,34 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) | |||
370 | * (possibly) execute vbios init tables (see nouveau_agp.h) | 387 | * (possibly) execute vbios init tables (see nouveau_agp.h) |
371 | */ | 388 | */ |
372 | if (pdev && drm_pci_device_is_agp(dev) && dev->agp) { | 389 | if (pdev && drm_pci_device_is_agp(dev) && dev->agp) { |
390 | const u64 enables = NV_DEVICE_V0_DISABLE_IDENTIFY | | ||
391 | NV_DEVICE_V0_DISABLE_MMIO; | ||
373 | /* dummy device object, doesn't init anything, but allows | 392 | /* dummy device object, doesn't init anything, but allows |
374 | * agp code access to registers | 393 | * agp code access to registers |
375 | */ | 394 | */ |
376 | ret = nouveau_object_new(nv_object(drm), NVDRM_CLIENT, | 395 | ret = nvif_device_init(&drm->client.base.base, NULL, |
377 | NVDRM_DEVICE, 0x0080, | 396 | NVDRM_DEVICE, NV_DEVICE, |
378 | &(struct nv_device_class) { | 397 | &(struct nv_device_v0) { |
379 | .device = ~0, | 398 | .device = ~0, |
380 | .disable = | 399 | .disable = ~enables, |
381 | ~(NV_DEVICE_DISABLE_MMIO | | ||
382 | NV_DEVICE_DISABLE_IDENTIFY), | ||
383 | .debug0 = ~0, | 400 | .debug0 = ~0, |
384 | }, sizeof(struct nv_device_class), | 401 | }, sizeof(struct nv_device_v0), |
385 | &drm->device); | 402 | &drm->device); |
386 | if (ret) | 403 | if (ret) |
387 | goto fail_device; | 404 | goto fail_device; |
388 | 405 | ||
389 | nouveau_agp_reset(drm); | 406 | nouveau_agp_reset(drm); |
390 | nouveau_object_del(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE); | 407 | nvif_device_fini(&drm->device); |
391 | } | 408 | } |
392 | 409 | ||
393 | ret = nouveau_object_new(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE, | 410 | ret = nvif_device_init(&drm->client.base.base, NULL, NVDRM_DEVICE, |
394 | 0x0080, &(struct nv_device_class) { | 411 | NV_DEVICE, |
412 | &(struct nv_device_v0) { | ||
395 | .device = ~0, | 413 | .device = ~0, |
396 | .disable = 0, | 414 | .disable = 0, |
397 | .debug0 = 0, | 415 | .debug0 = 0, |
398 | }, sizeof(struct nv_device_class), | 416 | }, sizeof(struct nv_device_v0), |
399 | &drm->device); | 417 | &drm->device); |
400 | if (ret) | 418 | if (ret) |
401 | goto fail_device; | 419 | goto fail_device; |
402 | 420 | ||
@@ -406,18 +424,19 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) | |||
406 | * nosnoop capability. hopefully won't cause issues until a | 424 | * nosnoop capability. hopefully won't cause issues until a |
407 | * better fix is found - assuming there is one... | 425 | * better fix is found - assuming there is one... |
408 | */ | 426 | */ |
409 | device = nv_device(drm->device); | 427 | if (drm->device.info.chipset == 0xc1) |
410 | if (nv_device(drm->device)->chipset == 0xc1) | 428 | nvif_mask(&drm->device, 0x00088080, 0x00000800, 0x00000000); |
411 | nv_mask(device, 0x00088080, 0x00000800, 0x00000000); | ||
412 | 429 | ||
413 | nouveau_vga_init(drm); | 430 | nouveau_vga_init(drm); |
414 | nouveau_agp_init(drm); | 431 | nouveau_agp_init(drm); |
415 | 432 | ||
416 | if (device->card_type >= NV_50) { | 433 | if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { |
417 | ret = nouveau_vm_new(nv_device(drm->device), 0, (1ULL << 40), | 434 | ret = nouveau_vm_new(nvkm_device(&drm->device), 0, (1ULL << 40), |
418 | 0x1000, &drm->client.base.vm); | 435 | 0x1000, &drm->client.vm); |
419 | if (ret) | 436 | if (ret) |
420 | goto fail_device; | 437 | goto fail_device; |
438 | |||
439 | nvkm_client(&drm->client.base)->vm = drm->client.vm; | ||
421 | } | 440 | } |
422 | 441 | ||
423 | ret = nouveau_ttm_init(drm); | 442 | ret = nouveau_ttm_init(drm); |
@@ -463,6 +482,7 @@ fail_ttm: | |||
463 | nouveau_agp_fini(drm); | 482 | nouveau_agp_fini(drm); |
464 | nouveau_vga_fini(drm); | 483 | nouveau_vga_fini(drm); |
465 | fail_device: | 484 | fail_device: |
485 | nvif_device_fini(&drm->device); | ||
466 | nouveau_cli_destroy(&drm->client); | 486 | nouveau_cli_destroy(&drm->client); |
467 | return ret; | 487 | return ret; |
468 | } | 488 | } |
@@ -488,26 +508,37 @@ nouveau_drm_unload(struct drm_device *dev) | |||
488 | nouveau_agp_fini(drm); | 508 | nouveau_agp_fini(drm); |
489 | nouveau_vga_fini(drm); | 509 | nouveau_vga_fini(drm); |
490 | 510 | ||
511 | nvif_device_fini(&drm->device); | ||
491 | if (drm->hdmi_device) | 512 | if (drm->hdmi_device) |
492 | pci_dev_put(drm->hdmi_device); | 513 | pci_dev_put(drm->hdmi_device); |
493 | nouveau_cli_destroy(&drm->client); | 514 | nouveau_cli_destroy(&drm->client); |
494 | return 0; | 515 | return 0; |
495 | } | 516 | } |
496 | 517 | ||
497 | static void | 518 | void |
498 | nouveau_drm_remove(struct pci_dev *pdev) | 519 | nouveau_drm_device_remove(struct drm_device *dev) |
499 | { | 520 | { |
500 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
501 | struct nouveau_drm *drm = nouveau_drm(dev); | 521 | struct nouveau_drm *drm = nouveau_drm(dev); |
522 | struct nouveau_client *client; | ||
502 | struct nouveau_object *device; | 523 | struct nouveau_object *device; |
503 | 524 | ||
504 | dev->irq_enabled = false; | 525 | dev->irq_enabled = false; |
505 | device = drm->client.base.device; | 526 | client = nvkm_client(&drm->client.base); |
527 | device = client->device; | ||
506 | drm_put_dev(dev); | 528 | drm_put_dev(dev); |
507 | 529 | ||
508 | nouveau_object_ref(NULL, &device); | 530 | nouveau_object_ref(NULL, &device); |
509 | nouveau_object_debug(); | 531 | nouveau_object_debug(); |
510 | } | 532 | } |
533 | EXPORT_SYMBOL(nouveau_drm_device_remove); | ||
534 | |||
535 | static void | ||
536 | nouveau_drm_remove(struct pci_dev *pdev) | ||
537 | { | ||
538 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
539 | |||
540 | nouveau_drm_device_remove(dev); | ||
541 | } | ||
511 | 542 | ||
512 | static int | 543 | static int |
513 | nouveau_do_suspend(struct drm_device *dev, bool runtime) | 544 | nouveau_do_suspend(struct drm_device *dev, bool runtime) |
@@ -548,13 +579,13 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime) | |||
548 | } | 579 | } |
549 | 580 | ||
550 | list_for_each_entry(cli, &drm->clients, head) { | 581 | list_for_each_entry(cli, &drm->clients, head) { |
551 | ret = nouveau_client_fini(&cli->base, true); | 582 | ret = nvif_client_suspend(&cli->base); |
552 | if (ret) | 583 | if (ret) |
553 | goto fail_client; | 584 | goto fail_client; |
554 | } | 585 | } |
555 | 586 | ||
556 | NV_INFO(drm, "suspending kernel object tree...\n"); | 587 | NV_INFO(drm, "suspending kernel object tree...\n"); |
557 | ret = nouveau_client_fini(&drm->client.base, true); | 588 | ret = nvif_client_suspend(&drm->client.base); |
558 | if (ret) | 589 | if (ret) |
559 | goto fail_client; | 590 | goto fail_client; |
560 | 591 | ||
@@ -563,7 +594,7 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime) | |||
563 | 594 | ||
564 | fail_client: | 595 | fail_client: |
565 | list_for_each_entry_continue_reverse(cli, &drm->clients, head) { | 596 | list_for_each_entry_continue_reverse(cli, &drm->clients, head) { |
566 | nouveau_client_init(&cli->base); | 597 | nvif_client_resume(&cli->base); |
567 | } | 598 | } |
568 | 599 | ||
569 | if (drm->fence && nouveau_fence(drm)->resume) | 600 | if (drm->fence && nouveau_fence(drm)->resume) |
@@ -611,7 +642,7 @@ nouveau_do_resume(struct drm_device *dev) | |||
611 | nouveau_agp_reset(drm); | 642 | nouveau_agp_reset(drm); |
612 | 643 | ||
613 | NV_INFO(drm, "resuming kernel object tree...\n"); | 644 | NV_INFO(drm, "resuming kernel object tree...\n"); |
614 | nouveau_client_init(&drm->client.base); | 645 | nvif_client_resume(&drm->client.base); |
615 | nouveau_agp_init(drm); | 646 | nouveau_agp_init(drm); |
616 | 647 | ||
617 | NV_INFO(drm, "resuming client object trees...\n"); | 648 | NV_INFO(drm, "resuming client object trees...\n"); |
@@ -619,7 +650,7 @@ nouveau_do_resume(struct drm_device *dev) | |||
619 | nouveau_fence(drm)->resume(drm); | 650 | nouveau_fence(drm)->resume(drm); |
620 | 651 | ||
621 | list_for_each_entry(cli, &drm->clients, head) { | 652 | list_for_each_entry(cli, &drm->clients, head) { |
622 | nouveau_client_init(&cli->base); | 653 | nvif_client_resume(&cli->base); |
623 | } | 654 | } |
624 | 655 | ||
625 | nouveau_run_vbios_init(dev); | 656 | nouveau_run_vbios_init(dev); |
@@ -715,13 +746,17 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) | |||
715 | if (ret) | 746 | if (ret) |
716 | goto out_suspend; | 747 | goto out_suspend; |
717 | 748 | ||
718 | if (nv_device(drm->device)->card_type >= NV_50) { | 749 | cli->base.super = false; |
719 | ret = nouveau_vm_new(nv_device(drm->device), 0, (1ULL << 40), | 750 | |
720 | 0x1000, &cli->base.vm); | 751 | if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { |
752 | ret = nouveau_vm_new(nvkm_device(&drm->device), 0, (1ULL << 40), | ||
753 | 0x1000, &cli->vm); | ||
721 | if (ret) { | 754 | if (ret) { |
722 | nouveau_cli_destroy(cli); | 755 | nouveau_cli_destroy(cli); |
723 | goto out_suspend; | 756 | goto out_suspend; |
724 | } | 757 | } |
758 | |||
759 | nvkm_client(&cli->base)->vm = cli->vm; | ||
725 | } | 760 | } |
726 | 761 | ||
727 | fpriv->driver_priv = cli; | 762 | fpriv->driver_priv = cli; |
@@ -779,24 +814,31 @@ nouveau_ioctls[] = { | |||
779 | DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), | 814 | DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), |
780 | }; | 815 | }; |
781 | 816 | ||
782 | long nouveau_drm_ioctl(struct file *filp, | 817 | long |
783 | unsigned int cmd, unsigned long arg) | 818 | nouveau_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
784 | { | 819 | { |
785 | struct drm_file *file_priv = filp->private_data; | 820 | struct drm_file *filp = file->private_data; |
786 | struct drm_device *dev; | 821 | struct drm_device *dev = filp->minor->dev; |
787 | long ret; | 822 | long ret; |
788 | dev = file_priv->minor->dev; | ||
789 | 823 | ||
790 | ret = pm_runtime_get_sync(dev->dev); | 824 | ret = pm_runtime_get_sync(dev->dev); |
791 | if (ret < 0 && ret != -EACCES) | 825 | if (ret < 0 && ret != -EACCES) |
792 | return ret; | 826 | return ret; |
793 | 827 | ||
794 | ret = drm_ioctl(filp, cmd, arg); | 828 | switch (_IOC_NR(cmd) - DRM_COMMAND_BASE) { |
829 | case DRM_NOUVEAU_NVIF: | ||
830 | ret = usif_ioctl(filp, (void __user *)arg, _IOC_SIZE(cmd)); | ||
831 | break; | ||
832 | default: | ||
833 | ret = drm_ioctl(file, cmd, arg); | ||
834 | break; | ||
835 | } | ||
795 | 836 | ||
796 | pm_runtime_mark_last_busy(dev->dev); | 837 | pm_runtime_mark_last_busy(dev->dev); |
797 | pm_runtime_put_autosuspend(dev->dev); | 838 | pm_runtime_put_autosuspend(dev->dev); |
798 | return ret; | 839 | return ret; |
799 | } | 840 | } |
841 | |||
800 | static const struct file_operations | 842 | static const struct file_operations |
801 | nouveau_driver_fops = { | 843 | nouveau_driver_fops = { |
802 | .owner = THIS_MODULE, | 844 | .owner = THIS_MODULE, |
@@ -921,7 +963,7 @@ static int nouveau_pmops_runtime_resume(struct device *dev) | |||
921 | { | 963 | { |
922 | struct pci_dev *pdev = to_pci_dev(dev); | 964 | struct pci_dev *pdev = to_pci_dev(dev); |
923 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | 965 | struct drm_device *drm_dev = pci_get_drvdata(pdev); |
924 | struct nouveau_device *device = nouveau_dev(drm_dev); | 966 | struct nvif_device *device = &nouveau_drm(drm_dev)->device; |
925 | int ret; | 967 | int ret; |
926 | 968 | ||
927 | if (nouveau_runtime_pm == 0) | 969 | if (nouveau_runtime_pm == 0) |
@@ -937,7 +979,7 @@ static int nouveau_pmops_runtime_resume(struct device *dev) | |||
937 | ret = nouveau_do_resume(drm_dev); | 979 | ret = nouveau_do_resume(drm_dev); |
938 | drm_kms_helper_poll_enable(drm_dev); | 980 | drm_kms_helper_poll_enable(drm_dev); |
939 | /* do magic */ | 981 | /* do magic */ |
940 | nv_mask(device, 0x88488, (1 << 25), (1 << 25)); | 982 | nvif_mask(device, 0x88488, (1 << 25), (1 << 25)); |
941 | vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON); | 983 | vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON); |
942 | drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; | 984 | drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; |
943 | nv_debug_level(NORMAL); | 985 | nv_debug_level(NORMAL); |
@@ -1005,24 +1047,41 @@ nouveau_drm_pci_driver = { | |||
1005 | .driver.pm = &nouveau_pm_ops, | 1047 | .driver.pm = &nouveau_pm_ops, |
1006 | }; | 1048 | }; |
1007 | 1049 | ||
1008 | int nouveau_drm_platform_probe(struct platform_device *pdev) | 1050 | struct drm_device * |
1051 | nouveau_platform_device_create_(struct platform_device *pdev, int size, | ||
1052 | void **pobject) | ||
1009 | { | 1053 | { |
1010 | struct nouveau_device *device; | 1054 | struct drm_device *drm; |
1011 | int ret; | 1055 | int err; |
1012 | 1056 | ||
1013 | ret = nouveau_device_create(pdev, NOUVEAU_BUS_PLATFORM, | 1057 | err = nouveau_device_create_(pdev, NOUVEAU_BUS_PLATFORM, |
1014 | nouveau_platform_name(pdev), | 1058 | nouveau_platform_name(pdev), |
1015 | dev_name(&pdev->dev), nouveau_config, | 1059 | dev_name(&pdev->dev), nouveau_config, |
1016 | nouveau_debug, &device); | 1060 | nouveau_debug, size, pobject); |
1017 | 1061 | if (err) | |
1018 | ret = drm_platform_init(&driver, pdev); | 1062 | return ERR_PTR(err); |
1019 | if (ret) { | 1063 | |
1020 | nouveau_object_ref(NULL, (struct nouveau_object **)&device); | 1064 | drm = drm_dev_alloc(&driver, &pdev->dev); |
1021 | return ret; | 1065 | if (!drm) { |
1066 | err = -ENOMEM; | ||
1067 | goto err_free; | ||
1022 | } | 1068 | } |
1023 | 1069 | ||
1024 | return ret; | 1070 | err = drm_dev_set_unique(drm, "%s", dev_name(&pdev->dev)); |
1071 | if (err < 0) | ||
1072 | goto err_free; | ||
1073 | |||
1074 | drm->platformdev = pdev; | ||
1075 | platform_set_drvdata(pdev, drm); | ||
1076 | |||
1077 | return drm; | ||
1078 | |||
1079 | err_free: | ||
1080 | nouveau_object_ref(NULL, (struct nouveau_object **)pobject); | ||
1081 | |||
1082 | return ERR_PTR(err); | ||
1025 | } | 1083 | } |
1084 | EXPORT_SYMBOL(nouveau_platform_device_create_); | ||
1026 | 1085 | ||
1027 | static int __init | 1086 | static int __init |
1028 | nouveau_drm_init(void) | 1087 | nouveau_drm_init(void) |