aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv04_fifo.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv04_fifo.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fifo.c367
1 files changed, 181 insertions, 186 deletions
diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c
index 584c24d457f0..a6295cd00ec7 100644
--- a/drivers/gpu/drm/nouveau/nv04_fifo.c
+++ b/drivers/gpu/drm/nouveau/nv04_fifo.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2007 Ben Skeggs. 2 * Copyright (C) 2012 Ben Skeggs.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * Permission is hereby granted, free of charge, to any person obtaining 5 * Permission is hereby granted, free of charge, to any person obtaining
@@ -27,21 +27,38 @@
27#include "drmP.h" 27#include "drmP.h"
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_fifo.h"
31#include "nouveau_util.h" 31#include "nouveau_util.h"
32 32#include "nouveau_ramht.h"
33#define NV04_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV04_RAMFC__SIZE)) 33#include "nouveau_software.h"
34#define NV04_RAMFC__SIZE 32 34
35#define NV04_RAMFC_DMA_PUT 0x00 35static struct ramfc_desc {
36#define NV04_RAMFC_DMA_GET 0x04 36 unsigned bits:6;
37#define NV04_RAMFC_DMA_INSTANCE 0x08 37 unsigned ctxs:5;
38#define NV04_RAMFC_DMA_STATE 0x0C 38 unsigned ctxp:8;
39#define NV04_RAMFC_DMA_FETCH 0x10 39 unsigned regs:5;
40#define NV04_RAMFC_ENGINE 0x14 40 unsigned regp;
41#define NV04_RAMFC_PULL1_ENGINE 0x18 41} nv04_ramfc[] = {
42 42 { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT },
43#define RAMFC_WR(offset, val) nv_wo32(chan->ramfc, NV04_RAMFC_##offset, (val)) 43 { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET },
44#define RAMFC_RD(offset) nv_ro32(chan->ramfc, NV04_RAMFC_##offset) 44 { 16, 0, 0x08, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE },
45 { 16, 16, 0x08, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT },
46 { 32, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_STATE },
47 { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_FETCH },
48 { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_ENGINE },
49 { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_PULL1 },
50 {}
51};
52
53struct nv04_fifo_priv {
54 struct nouveau_fifo_priv base;
55 struct ramfc_desc *ramfc_desc;
56};
57
58struct nv04_fifo_chan {
59 struct nouveau_fifo_chan base;
60 struct nouveau_gpuobj *ramfc;
61};
45 62
46bool 63bool
47nv04_fifo_cache_pull(struct drm_device *dev, bool enable) 64nv04_fifo_cache_pull(struct drm_device *dev, bool enable)
@@ -58,13 +75,13 @@ nv04_fifo_cache_pull(struct drm_device *dev, bool enable)
58 * invalidate the most recently calculated instance. 75 * invalidate the most recently calculated instance.
59 */ 76 */
60 if (!nv_wait(dev, NV04_PFIFO_CACHE1_PULL0, 77 if (!nv_wait(dev, NV04_PFIFO_CACHE1_PULL0,
61 NV04_PFIFO_CACHE1_PULL0_HASH_BUSY, 0)) 78 NV04_PFIFO_CACHE1_PULL0_HASH_BUSY, 0))
62 NV_ERROR(dev, "Timeout idling the PFIFO puller.\n"); 79 NV_ERROR(dev, "Timeout idling the PFIFO puller.\n");
63 80
64 if (nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0) & 81 if (nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0) &
65 NV04_PFIFO_CACHE1_PULL0_HASH_FAILED) 82 NV04_PFIFO_CACHE1_PULL0_HASH_FAILED)
66 nv_wr32(dev, NV03_PFIFO_INTR_0, 83 nv_wr32(dev, NV03_PFIFO_INTR_0,
67 NV_PFIFO_INTR_CACHE_ERROR); 84 NV_PFIFO_INTR_CACHE_ERROR);
68 85
69 nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); 86 nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0);
70 } 87 }
@@ -72,238 +89,182 @@ nv04_fifo_cache_pull(struct drm_device *dev, bool enable)
72 return pull & 1; 89 return pull & 1;
73} 90}
74 91
75#ifdef __BIG_ENDIAN 92static int
76#define DMA_FETCH_ENDIANNESS NV_PFIFO_CACHE1_BIG_ENDIAN 93nv04_fifo_context_new(struct nouveau_channel *chan, int engine)
77#else
78#define DMA_FETCH_ENDIANNESS 0
79#endif
80
81int
82nv04_fifo_create_context(struct nouveau_channel *chan)
83{ 94{
84 struct drm_device *dev = chan->dev; 95 struct drm_device *dev = chan->dev;
85 struct drm_nouveau_private *dev_priv = dev->dev_private; 96 struct drm_nouveau_private *dev_priv = dev->dev_private;
97 struct nv04_fifo_priv *priv = nv_engine(dev, engine);
98 struct nv04_fifo_chan *fctx;
86 unsigned long flags; 99 unsigned long flags;
87 int ret; 100 int ret;
88 101
89 ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(chan->id), ~0, 102 fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL);
90 NV04_RAMFC__SIZE, 103 if (!fctx)
91 NVOBJ_FLAG_ZERO_ALLOC | 104 return -ENOMEM;
92 NVOBJ_FLAG_ZERO_FREE,
93 &chan->ramfc);
94 if (ret)
95 return ret;
96 105
106 /* map channel control registers */
97 chan->user = ioremap(pci_resource_start(dev->pdev, 0) + 107 chan->user = ioremap(pci_resource_start(dev->pdev, 0) +
98 NV03_USER(chan->id), PAGE_SIZE); 108 NV03_USER(chan->id), PAGE_SIZE);
99 if (!chan->user) 109 if (!chan->user) {
100 return -ENOMEM; 110 ret = -ENOMEM;
101 111 goto error;
102 spin_lock_irqsave(&dev_priv->context_switch_lock, flags); 112 }
103
104 /* Setup initial state */
105 RAMFC_WR(DMA_PUT, chan->pushbuf_base);
106 RAMFC_WR(DMA_GET, chan->pushbuf_base);
107 RAMFC_WR(DMA_INSTANCE, chan->pushbuf->pinst >> 4);
108 RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
109 NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
110 NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
111 DMA_FETCH_ENDIANNESS));
112 113
113 /* enable the fifo dma operation */ 114 /* initialise default fifo context */
114 nv_wr32(dev, NV04_PFIFO_MODE, 115 ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramfc->pinst +
115 nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id)); 116 chan->id * 32, ~0, 32,
117 NVOBJ_FLAG_ZERO_FREE, &fctx->ramfc);
118 if (ret)
119 goto error;
120
121 nv_wo32(fctx->ramfc, 0x00, chan->pushbuf_base);
122 nv_wo32(fctx->ramfc, 0x04, chan->pushbuf_base);
123 nv_wo32(fctx->ramfc, 0x08, chan->pushbuf->pinst >> 4);
124 nv_wo32(fctx->ramfc, 0x0c, 0x00000000);
125 nv_wo32(fctx->ramfc, 0x10, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
126 NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
127#ifdef __BIG_ENDIAN
128 NV_PFIFO_CACHE1_BIG_ENDIAN |
129#endif
130 NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8);
131 nv_wo32(fctx->ramfc, 0x14, 0x00000000);
132 nv_wo32(fctx->ramfc, 0x18, 0x00000000);
133 nv_wo32(fctx->ramfc, 0x1c, 0x00000000);
116 134
135 /* enable dma mode on the channel */
136 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
137 nv_mask(dev, NV04_PFIFO_MODE, (1 << chan->id), (1 << chan->id));
117 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); 138 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
118 return 0; 139
140error:
141 if (ret)
142 priv->base.base.context_del(chan, engine);
143 return ret;
119} 144}
120 145
121void 146void
122nv04_fifo_destroy_context(struct nouveau_channel *chan) 147nv04_fifo_context_del(struct nouveau_channel *chan, int engine)
123{ 148{
124 struct drm_device *dev = chan->dev; 149 struct drm_device *dev = chan->dev;
125 struct drm_nouveau_private *dev_priv = dev->dev_private; 150 struct drm_nouveau_private *dev_priv = dev->dev_private;
126 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 151 struct nv04_fifo_priv *priv = nv_engine(chan->dev, engine);
152 struct nv04_fifo_chan *fctx = chan->engctx[engine];
153 struct ramfc_desc *c = priv->ramfc_desc;
127 unsigned long flags; 154 unsigned long flags;
155 int chid;
128 156
157 /* prevent fifo context switches */
129 spin_lock_irqsave(&dev_priv->context_switch_lock, flags); 158 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
130 nv_wr32(dev, NV03_PFIFO_CACHES, 0); 159 nv_wr32(dev, NV03_PFIFO_CACHES, 0);
131 160
132 /* Unload the context if it's the currently active one */ 161 /* if this channel is active, replace it with a null context */
133 if ((nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & 0xf) == chan->id) { 162 chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & priv->base.channels;
163 if (chid == chan->id) {
134 nv_mask(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0); 164 nv_mask(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0);
135 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 0); 165 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 0);
136 nv_mask(dev, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); 166 nv_mask(dev, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0);
137 pfifo->unload_context(dev); 167
168 do {
169 u32 mask = ((1ULL << c->bits) - 1) << c->regs;
170 nv_mask(dev, c->regp, mask, 0x00000000);
171 } while ((++c)->bits);
172
173 nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
174 nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
175 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels);
138 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); 176 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1);
139 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); 177 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
140 } 178 }
141 179
142 /* Keep it from being rescheduled */ 180 /* restore normal operation, after disabling dma mode */
143 nv_mask(dev, NV04_PFIFO_MODE, 1 << chan->id, 0); 181 nv_mask(dev, NV04_PFIFO_MODE, 1 << chan->id, 0);
144 nv_wr32(dev, NV03_PFIFO_CACHES, 1); 182 nv_wr32(dev, NV03_PFIFO_CACHES, 1);
145 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); 183 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
146 184
147 /* Free the channel resources */ 185 /* clean up */
186 nouveau_gpuobj_ref(NULL, &fctx->ramfc);
187 nouveau_gpuobj_ref(NULL, &chan->ramfc); /*XXX: nv40 */
148 if (chan->user) { 188 if (chan->user) {
149 iounmap(chan->user); 189 iounmap(chan->user);
150 chan->user = NULL; 190 chan->user = NULL;
151 } 191 }
152 nouveau_gpuobj_ref(NULL, &chan->ramfc);
153}
154
155static void
156nv04_fifo_do_load_context(struct drm_device *dev, int chid)
157{
158 struct drm_nouveau_private *dev_priv = dev->dev_private;
159 uint32_t fc = NV04_RAMFC(chid), tmp;
160
161 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
162 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
163 tmp = nv_ri32(dev, fc + 8);
164 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE, tmp & 0xFFFF);
165 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT, tmp >> 16);
166 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, nv_ri32(dev, fc + 12));
167 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_FETCH, nv_ri32(dev, fc + 16));
168 nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 20));
169 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 24));
170
171 nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
172 nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
173} 192}
174 193
175int 194int
176nv04_fifo_load_context(struct nouveau_channel *chan) 195nv04_fifo_init(struct drm_device *dev, int engine)
177{
178 uint32_t tmp;
179
180 nv_wr32(chan->dev, NV03_PFIFO_CACHE1_PUSH1,
181 NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id);
182 nv04_fifo_do_load_context(chan->dev, chan->id);
183 nv_wr32(chan->dev, NV04_PFIFO_CACHE1_DMA_PUSH, 1);
184
185 /* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */
186 tmp = nv_rd32(chan->dev, NV04_PFIFO_CACHE1_DMA_CTL) & ~(1 << 31);
187 nv_wr32(chan->dev, NV04_PFIFO_CACHE1_DMA_CTL, tmp);
188
189 return 0;
190}
191
192int
193nv04_fifo_unload_context(struct drm_device *dev)
194{ 196{
195 struct drm_nouveau_private *dev_priv = dev->dev_private; 197 struct drm_nouveau_private *dev_priv = dev->dev_private;
196 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 198 struct nv04_fifo_priv *priv = nv_engine(dev, engine);
197 struct nouveau_channel *chan = NULL; 199 int i;
198 uint32_t tmp;
199 int chid;
200 200
201 chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & 0xf; 201 nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, 0);
202 if (chid < 0 || chid >= dev_priv->engine.fifo.channels) 202 nv_mask(dev, NV03_PMC_ENABLE, NV_PMC_ENABLE_PFIFO, NV_PMC_ENABLE_PFIFO);
203 return 0;
204 203
205 chan = dev_priv->channels.ptr[chid]; 204 nv_wr32(dev, NV04_PFIFO_DELAY_0, 0x000000ff);
206 if (!chan) { 205 nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, 0x0101ffff);
207 NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid);
208 return -EINVAL;
209 }
210
211 RAMFC_WR(DMA_PUT, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
212 RAMFC_WR(DMA_GET, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
213 tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16;
214 tmp |= nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE);
215 RAMFC_WR(DMA_INSTANCE, tmp);
216 RAMFC_WR(DMA_STATE, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_STATE));
217 RAMFC_WR(DMA_FETCH, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH));
218 RAMFC_WR(ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE));
219 RAMFC_WR(PULL1_ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1));
220
221 nv04_fifo_do_load_context(dev, pfifo->channels - 1);
222 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
223 return 0;
224}
225
226static void
227nv04_fifo_init_reset(struct drm_device *dev)
228{
229 nv_wr32(dev, NV03_PMC_ENABLE,
230 nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PFIFO);
231 nv_wr32(dev, NV03_PMC_ENABLE,
232 nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PFIFO);
233
234 nv_wr32(dev, 0x003224, 0x000f0078);
235 nv_wr32(dev, 0x002044, 0x0101ffff);
236 nv_wr32(dev, 0x002040, 0x000000ff);
237 nv_wr32(dev, 0x002500, 0x00000000);
238 nv_wr32(dev, 0x003000, 0x00000000);
239 nv_wr32(dev, 0x003050, 0x00000000);
240 nv_wr32(dev, 0x003200, 0x00000000);
241 nv_wr32(dev, 0x003250, 0x00000000);
242 nv_wr32(dev, 0x003220, 0x00000000);
243
244 nv_wr32(dev, 0x003250, 0x00000000);
245 nv_wr32(dev, 0x003270, 0x00000000);
246 nv_wr32(dev, 0x003210, 0x00000000);
247}
248
249static void
250nv04_fifo_init_ramxx(struct drm_device *dev)
251{
252 struct drm_nouveau_private *dev_priv = dev->dev_private;
253 206
254 nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | 207 nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ |
255 ((dev_priv->ramht->bits - 9) << 16) | 208 ((dev_priv->ramht->bits - 9) << 16) |
256 (dev_priv->ramht->gpuobj->pinst >> 8)); 209 (dev_priv->ramht->gpuobj->pinst >> 8));
257 nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8); 210 nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8);
258 nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc->pinst >> 8); 211 nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc->pinst >> 8);
259}
260 212
261static void 213 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, priv->base.channels);
262nv04_fifo_init_intr(struct drm_device *dev)
263{
264 nouveau_irq_register(dev, 8, nv04_fifo_isr);
265 nv_wr32(dev, 0x002100, 0xffffffff);
266 nv_wr32(dev, 0x002140, 0xffffffff);
267}
268 214
269int 215 nv_wr32(dev, NV03_PFIFO_INTR_0, 0xffffffff);
270nv04_fifo_init(struct drm_device *dev) 216 nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xffffffff);
271{
272 struct drm_nouveau_private *dev_priv = dev->dev_private;
273 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
274 int i;
275 217
276 nv04_fifo_init_reset(dev);
277 nv04_fifo_init_ramxx(dev);
278
279 nv04_fifo_do_load_context(dev, pfifo->channels - 1);
280 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
281
282 nv04_fifo_init_intr(dev);
283 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1); 218 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1);
284 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); 219 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
285 nv_wr32(dev, NV03_PFIFO_CACHES, 1); 220 nv_wr32(dev, NV03_PFIFO_CACHES, 1);
286 221
287 for (i = 0; i < dev_priv->engine.fifo.channels; i++) { 222 for (i = 0; i < priv->base.channels; i++) {
288 if (dev_priv->channels.ptr[i]) { 223 if (dev_priv->channels.ptr[i])
289 uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); 224 nv_mask(dev, NV04_PFIFO_MODE, (1 << i), (1 << i));
290 nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i));
291 }
292 } 225 }
293 226
294 return 0; 227 return 0;
295} 228}
296 229
297void 230int
298nv04_fifo_fini(struct drm_device *dev) 231nv04_fifo_fini(struct drm_device *dev, int engine, bool suspend)
299{ 232{
300 nv_wr32(dev, 0x2140, 0x00000000); 233 struct drm_nouveau_private *dev_priv = dev->dev_private;
301 nouveau_irq_unregister(dev, 8); 234 struct nv04_fifo_priv *priv = nv_engine(dev, engine);
235 struct nouveau_channel *chan;
236 int chid;
237
238 /* prevent context switches and halt fifo operation */
239 nv_wr32(dev, NV03_PFIFO_CACHES, 0);
240 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0);
241 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 0);
242 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 0);
243
244 /* store current fifo context in ramfc */
245 chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & priv->base.channels;
246 chan = dev_priv->channels.ptr[chid];
247 if (suspend && chid != priv->base.channels && chan) {
248 struct nv04_fifo_chan *fctx = chan->engctx[engine];
249 struct nouveau_gpuobj *ctx = fctx->ramfc;
250 struct ramfc_desc *c = priv->ramfc_desc;
251 do {
252 u32 rm = ((1ULL << c->bits) - 1) << c->regs;
253 u32 cm = ((1ULL << c->bits) - 1) << c->ctxs;
254 u32 rv = (nv_rd32(dev, c->regp) & rm) >> c->regs;
255 u32 cv = (nv_ro32(ctx, c->ctxp) & ~cm);
256 nv_wo32(ctx, c->ctxp, cv | (rv << c->ctxs));
257 } while ((++c)->bits);
258 }
259
260 nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0x00000000);
261 return 0;
302} 262}
303 263
304static bool 264static bool
305nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data) 265nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
306{ 266{
267 struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO);
307 struct drm_nouveau_private *dev_priv = dev->dev_private; 268 struct drm_nouveau_private *dev_priv = dev->dev_private;
308 struct nouveau_channel *chan = NULL; 269 struct nouveau_channel *chan = NULL;
309 struct nouveau_gpuobj *obj; 270 struct nouveau_gpuobj *obj;
@@ -314,7 +275,7 @@ nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
314 u32 engine; 275 u32 engine;
315 276
316 spin_lock_irqsave(&dev_priv->channels.lock, flags); 277 spin_lock_irqsave(&dev_priv->channels.lock, flags);
317 if (likely(chid >= 0 && chid < dev_priv->engine.fifo.channels)) 278 if (likely(chid >= 0 && chid < pfifo->channels))
318 chan = dev_priv->channels.ptr[chid]; 279 chan = dev_priv->channels.ptr[chid];
319 if (unlikely(!chan)) 280 if (unlikely(!chan))
320 goto out; 281 goto out;
@@ -325,7 +286,6 @@ nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
325 if (unlikely(!obj || obj->engine != NVOBJ_ENGINE_SW)) 286 if (unlikely(!obj || obj->engine != NVOBJ_ENGINE_SW))
326 break; 287 break;
327 288
328 chan->sw_subchannel[subc] = obj->class;
329 engine = 0x0000000f << (subc * 4); 289 engine = 0x0000000f << (subc * 4);
330 290
331 nv_mask(dev, NV04_PFIFO_CACHE1_ENGINE, engine, 0x00000000); 291 nv_mask(dev, NV04_PFIFO_CACHE1_ENGINE, engine, 0x00000000);
@@ -336,7 +296,7 @@ nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
336 if (unlikely(((engine >> (subc * 4)) & 0xf) != 0)) 296 if (unlikely(((engine >> (subc * 4)) & 0xf) != 0))
337 break; 297 break;
338 298
339 if (!nouveau_gpuobj_mthd_call(chan, chan->sw_subchannel[subc], 299 if (!nouveau_gpuobj_mthd_call(chan, nouveau_software_class(dev),
340 mthd, data)) 300 mthd, data))
341 handled = true; 301 handled = true;
342 break; 302 break;
@@ -359,6 +319,7 @@ static const char *nv_dma_state_err(u32 state)
359void 319void
360nv04_fifo_isr(struct drm_device *dev) 320nv04_fifo_isr(struct drm_device *dev)
361{ 321{
322 struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO);
362 struct drm_nouveau_private *dev_priv = dev->dev_private; 323 struct drm_nouveau_private *dev_priv = dev->dev_private;
363 uint32_t status, reassign; 324 uint32_t status, reassign;
364 int cnt = 0; 325 int cnt = 0;
@@ -369,8 +330,7 @@ nv04_fifo_isr(struct drm_device *dev)
369 330
370 nv_wr32(dev, NV03_PFIFO_CACHES, 0); 331 nv_wr32(dev, NV03_PFIFO_CACHES, 0);
371 332
372 chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1); 333 chid = nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) & pfifo->channels;
373 chid &= dev_priv->engine.fifo.channels - 1;
374 get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET); 334 get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET);
375 335
376 if (status & NV_PFIFO_INTR_CACHE_ERROR) { 336 if (status & NV_PFIFO_INTR_CACHE_ERROR) {
@@ -509,3 +469,38 @@ nv04_fifo_isr(struct drm_device *dev)
509 469
510 nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING); 470 nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
511} 471}
472
473void
474nv04_fifo_destroy(struct drm_device *dev, int engine)
475{
476 struct drm_nouveau_private *dev_priv = dev->dev_private;
477 struct nv04_fifo_priv *priv = nv_engine(dev, engine);
478
479 nouveau_irq_unregister(dev, 8);
480
481 dev_priv->eng[engine] = NULL;
482 kfree(priv);
483}
484
485int
486nv04_fifo_create(struct drm_device *dev)
487{
488 struct drm_nouveau_private *dev_priv = dev->dev_private;
489 struct nv04_fifo_priv *priv;
490
491 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
492 if (!priv)
493 return -ENOMEM;
494
495 priv->base.base.destroy = nv04_fifo_destroy;
496 priv->base.base.init = nv04_fifo_init;
497 priv->base.base.fini = nv04_fifo_fini;
498 priv->base.base.context_new = nv04_fifo_context_new;
499 priv->base.base.context_del = nv04_fifo_context_del;
500 priv->base.channels = 15;
501 priv->ramfc_desc = nv04_ramfc;
502 dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base;
503
504 nouveau_irq_register(dev, 8, nv04_fifo_isr);
505 return 0;
506}