diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_fifo.c')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv50_fifo.c | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c index 1da65bd60c10..8dd04c5dac67 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include "drm.h" | 28 | #include "drm.h" |
| 29 | #include "nouveau_drv.h" | 29 | #include "nouveau_drv.h" |
| 30 | #include "nouveau_ramht.h" | 30 | #include "nouveau_ramht.h" |
| 31 | #include "nouveau_vm.h" | ||
| 31 | 32 | ||
| 32 | static void | 33 | static void |
| 33 | nv50_fifo_playlist_update(struct drm_device *dev) | 34 | nv50_fifo_playlist_update(struct drm_device *dev) |
| @@ -44,7 +45,8 @@ nv50_fifo_playlist_update(struct drm_device *dev) | |||
| 44 | 45 | ||
| 45 | /* We never schedule channel 0 or 127 */ | 46 | /* We never schedule channel 0 or 127 */ |
| 46 | for (i = 1, nr = 0; i < 127; i++) { | 47 | for (i = 1, nr = 0; i < 127; i++) { |
| 47 | if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) { | 48 | if (dev_priv->channels.ptr[i] && |
| 49 | dev_priv->channels.ptr[i]->ramfc) { | ||
| 48 | nv_wo32(cur, (nr * 4), i); | 50 | nv_wo32(cur, (nr * 4), i); |
| 49 | nr++; | 51 | nr++; |
| 50 | } | 52 | } |
| @@ -60,7 +62,7 @@ static void | |||
| 60 | nv50_fifo_channel_enable(struct drm_device *dev, int channel) | 62 | nv50_fifo_channel_enable(struct drm_device *dev, int channel) |
| 61 | { | 63 | { |
| 62 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 64 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 63 | struct nouveau_channel *chan = dev_priv->fifos[channel]; | 65 | struct nouveau_channel *chan = dev_priv->channels.ptr[channel]; |
| 64 | uint32_t inst; | 66 | uint32_t inst; |
| 65 | 67 | ||
| 66 | NV_DEBUG(dev, "ch%d\n", channel); | 68 | NV_DEBUG(dev, "ch%d\n", channel); |
| @@ -105,6 +107,7 @@ nv50_fifo_init_intr(struct drm_device *dev) | |||
| 105 | { | 107 | { |
| 106 | NV_DEBUG(dev, "\n"); | 108 | NV_DEBUG(dev, "\n"); |
| 107 | 109 | ||
| 110 | nouveau_irq_register(dev, 8, nv04_fifo_isr); | ||
| 108 | nv_wr32(dev, NV03_PFIFO_INTR_0, 0xFFFFFFFF); | 111 | nv_wr32(dev, NV03_PFIFO_INTR_0, 0xFFFFFFFF); |
| 109 | nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF); | 112 | nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF); |
| 110 | } | 113 | } |
| @@ -118,7 +121,7 @@ nv50_fifo_init_context_table(struct drm_device *dev) | |||
| 118 | NV_DEBUG(dev, "\n"); | 121 | NV_DEBUG(dev, "\n"); |
| 119 | 122 | ||
| 120 | for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) { | 123 | for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) { |
| 121 | if (dev_priv->fifos[i]) | 124 | if (dev_priv->channels.ptr[i]) |
| 122 | nv50_fifo_channel_enable(dev, i); | 125 | nv50_fifo_channel_enable(dev, i); |
| 123 | else | 126 | else |
| 124 | nv50_fifo_channel_disable(dev, i); | 127 | nv50_fifo_channel_disable(dev, i); |
| @@ -206,6 +209,9 @@ nv50_fifo_takedown(struct drm_device *dev) | |||
| 206 | if (!pfifo->playlist[0]) | 209 | if (!pfifo->playlist[0]) |
| 207 | return; | 210 | return; |
| 208 | 211 | ||
| 212 | nv_wr32(dev, 0x2140, 0x00000000); | ||
| 213 | nouveau_irq_unregister(dev, 8); | ||
| 214 | |||
| 209 | nouveau_gpuobj_ref(NULL, &pfifo->playlist[0]); | 215 | nouveau_gpuobj_ref(NULL, &pfifo->playlist[0]); |
| 210 | nouveau_gpuobj_ref(NULL, &pfifo->playlist[1]); | 216 | nouveau_gpuobj_ref(NULL, &pfifo->playlist[1]); |
| 211 | } | 217 | } |
| @@ -256,6 +262,11 @@ nv50_fifo_create_context(struct nouveau_channel *chan) | |||
| 256 | } | 262 | } |
| 257 | ramfc = chan->ramfc; | 263 | ramfc = chan->ramfc; |
| 258 | 264 | ||
| 265 | chan->user = ioremap(pci_resource_start(dev->pdev, 0) + | ||
| 266 | NV50_USER(chan->id), PAGE_SIZE); | ||
| 267 | if (!chan->user) | ||
| 268 | return -ENOMEM; | ||
| 269 | |||
| 259 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | 270 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); |
| 260 | 271 | ||
| 261 | nv_wo32(ramfc, 0x48, chan->pushbuf->cinst >> 4); | 272 | nv_wo32(ramfc, 0x48, chan->pushbuf->cinst >> 4); |
| @@ -291,10 +302,23 @@ void | |||
| 291 | nv50_fifo_destroy_context(struct nouveau_channel *chan) | 302 | nv50_fifo_destroy_context(struct nouveau_channel *chan) |
| 292 | { | 303 | { |
| 293 | struct drm_device *dev = chan->dev; | 304 | struct drm_device *dev = chan->dev; |
| 305 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 306 | struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; | ||
| 294 | struct nouveau_gpuobj *ramfc = NULL; | 307 | struct nouveau_gpuobj *ramfc = NULL; |
| 308 | unsigned long flags; | ||
| 295 | 309 | ||
| 296 | NV_DEBUG(dev, "ch%d\n", chan->id); | 310 | NV_DEBUG(dev, "ch%d\n", chan->id); |
| 297 | 311 | ||
| 312 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | ||
| 313 | pfifo->reassign(dev, false); | ||
| 314 | |||
| 315 | /* Unload the context if it's the currently active one */ | ||
| 316 | if (pfifo->channel_id(dev) == chan->id) { | ||
| 317 | pfifo->disable(dev); | ||
| 318 | pfifo->unload_context(dev); | ||
| 319 | pfifo->enable(dev); | ||
| 320 | } | ||
| 321 | |||
| 298 | /* This will ensure the channel is seen as disabled. */ | 322 | /* This will ensure the channel is seen as disabled. */ |
| 299 | nouveau_gpuobj_ref(chan->ramfc, &ramfc); | 323 | nouveau_gpuobj_ref(chan->ramfc, &ramfc); |
| 300 | nouveau_gpuobj_ref(NULL, &chan->ramfc); | 324 | nouveau_gpuobj_ref(NULL, &chan->ramfc); |
| @@ -305,6 +329,14 @@ nv50_fifo_destroy_context(struct nouveau_channel *chan) | |||
| 305 | nv50_fifo_channel_disable(dev, 127); | 329 | nv50_fifo_channel_disable(dev, 127); |
| 306 | nv50_fifo_playlist_update(dev); | 330 | nv50_fifo_playlist_update(dev); |
| 307 | 331 | ||
| 332 | pfifo->reassign(dev, true); | ||
| 333 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); | ||
| 334 | |||
| 335 | /* Free the channel resources */ | ||
| 336 | if (chan->user) { | ||
| 337 | iounmap(chan->user); | ||
| 338 | chan->user = NULL; | ||
| 339 | } | ||
| 308 | nouveau_gpuobj_ref(NULL, &ramfc); | 340 | nouveau_gpuobj_ref(NULL, &ramfc); |
| 309 | nouveau_gpuobj_ref(NULL, &chan->cache); | 341 | nouveau_gpuobj_ref(NULL, &chan->cache); |
| 310 | } | 342 | } |
| @@ -392,7 +424,7 @@ nv50_fifo_unload_context(struct drm_device *dev) | |||
| 392 | if (chid < 1 || chid >= dev_priv->engine.fifo.channels - 1) | 424 | if (chid < 1 || chid >= dev_priv->engine.fifo.channels - 1) |
| 393 | return 0; | 425 | return 0; |
| 394 | 426 | ||
| 395 | chan = dev_priv->fifos[chid]; | 427 | chan = dev_priv->channels.ptr[chid]; |
| 396 | if (!chan) { | 428 | if (!chan) { |
| 397 | NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid); | 429 | NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid); |
| 398 | return -EINVAL; | 430 | return -EINVAL; |
| @@ -467,5 +499,5 @@ nv50_fifo_unload_context(struct drm_device *dev) | |||
| 467 | void | 499 | void |
| 468 | nv50_fifo_tlb_flush(struct drm_device *dev) | 500 | nv50_fifo_tlb_flush(struct drm_device *dev) |
| 469 | { | 501 | { |
| 470 | nv50_vm_flush(dev, 5); | 502 | nv50_vm_flush_engine(dev, 5); |
| 471 | } | 503 | } |
