1/* 2 * Copyright 2010 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Ben Skeggs 23 */ 24 25#include "drmP.h" 26 27#include "nouveau_drv.h" 28#include "nouveau_mm.h" 29 30static void nvc0_fifo_isr(struct drm_device *); 31 32struct nvc0_fifo_priv { 33 struct nouveau_gpuobj *playlist[2]; 34 int cur_playlist; 35 struct nouveau_vma user_vma; 36 int spoon_nr; 37}; 38 39struct nvc0_fifo_chan { 40 struct nouveau_gpuobj *user; 41 struct nouveau_gpuobj *ramfc; 42}; 43 44static void 45nvc0_fifo_playlist_update(struct drm_device *dev) 46{ 47 struct drm_nouveau_private *dev_priv = dev->dev_private; 48 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; 49 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 50 struct nvc0_fifo_priv *priv = pfifo->priv; 51 struct nouveau_gpuobj *cur; 52 int i, p; 53 54 cur = priv->playlist[priv->cur_playlist]; 55 priv->cur_playlist = !priv->cur_playlist; 56 57 for (i = 0, p = 0; i < 128; i++) { 58 if (!(nv_rd32(dev, 0x3004 + (i * 8)) & 1)) 59 continue; 60 nv_wo32(cur, p + 0, i); 61 nv_wo32(cur, p + 4, 0x00000004); 62 p += 8; 63 } 64 pinstmem->flush(dev); 65 66 nv_wr32(dev, 0x002270, cur->vinst >> 12); 67 nv_wr32(dev, 0x002274, 0x01f00000 | (p >> 3)); 68 if (!nv_wait(dev, 0x00227c, 0x00100000, 0x00000000)) 69 NV_ERROR(dev, "PFIFO - playlist update failed\n"); 70} 71 72void 73nvc0_fifo_disable(struct drm_device *dev) 74{ 75} 76 77void 78nvc0_fifo_enable(struct drm_device *dev) 79{ 80} 81 82bool 83nvc0_fifo_reassign(struct drm_device *dev, bool enable) 84{ 85 return false; 86} 87 88bool 89nvc0_fifo_cache_pull(struct drm_device *dev, bool enable) 90{ 91 return false; 92} 93 94int 95nvc0_fifo_channel_id(struct drm_device *dev) 96{ 97 return 127; 98} 99 100int 101nvc0_fifo_create_context(struct nouveau_channel *chan) 102{ 103 struct drm_device *dev = chan->dev; 104 struct drm_nouveau_private *dev_priv = dev->dev_private; 105 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; 106 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 107 struct nvc0_fifo_priv *priv = pfifo->priv; 108 struct nvc0_fifo_chan *fifoch; 109 u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4; 110 int ret; 111 112 chan->fifo_priv = kzalloc(sizeof(*fifoch), GFP_KERNEL); 113 if (!chan->fifo_priv) 114 return -ENOMEM; 115 fifoch = chan->fifo_priv; 116 117 /* allocate vram for control regs, map into polling area */ 118 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000, 119 NVOBJ_FLAG_ZERO_ALLOC, &fifoch->user); 120 if (ret) 121 goto error; 122 123 nouveau_vm_map_at(&priv->user_vma, chan->id * 0x1000, 124 *(struct nouveau_mem **)fifoch->user->node); 125 126 chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) + 127 priv->user_vma.offset + (chan->id * 0x1000), 128 PAGE_SIZE); 129 if (!chan->user) { 130 ret = -ENOMEM; 131 goto error; 132 } 133 134 /* ramfc */ 135 ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst, 136 chan->ramin->vinst, 0x100, 137 NVOBJ_FLAG_ZERO_ALLOC, &fifoch->ramfc); 138 if (ret) 139 goto error; 140 141 nv_wo32(fifoch->ramfc, 0x08, lower_32_bits(fifoch->user->vinst)); 142 nv_wo32(fifoch->ramfc, 0x0c, upper_32_bits(fifoch->user->vinst)); 143 nv_wo32(fifoch->ramfc, 0x10, 0x0000face); 144 nv_wo32(fifoch->ramfc, 0x30, 0xfffff902); 145 nv_wo32(fifoch->ramfc, 0x48, lower_32_bits(ib_virt)); 146 nv_wo32(fifoch->ramfc, 0x4c, drm_order(chan->dma.ib_max + 1) << 16 | 147 upper_32_bits(ib_virt)); 148 nv_wo32(fifoch->ramfc, 0x54, 0x00000002); 149 nv_wo32(fifoch->ramfc, 0x84, 0x20400000); 150 nv_wo32(fifoch->ramfc, 0x94, 0x30000001); 151 nv_wo32(fifoch->ramfc, 0x9c, 0x00000100); 152 nv_wo32(fifoch->ramfc, 0xa4, 0x1f1f1f1f); 153 nv_wo32(fifoch->ramfc, 0xa8, 0x1f1f1f1f); 154 nv_wo32(fifoch->ramfc, 0xac, 0x0000001f); 155 nv_wo32(fifoch->ramfc, 0xb8, 0xf8000000); 156 nv_wo32(fifoch->ramfc, 0xf8, 0x10003080); /* 0x002310 */ 157 nv_wo32(fifoch->ramfc, 0xfc, 0x10000010); /* 0x002350 */ 158 pinstmem->flush(dev); 159 160 nv_wr32(dev, 0x003000 + (chan->id * 8), 0xc0000000 | 161 (chan->ramin->vinst >> 12)); 162 nv_wr32(dev, 0x003004 + (chan->id * 8), 0x001f0001); 163 nvc0_fifo_playlist_update(dev); 164 return 0; 165 166error: 167 pfifo->destroy_context(chan); 168 return ret; 169} 170 171void 172nvc0_fifo_destroy_context(struct nouveau_channel *chan) 173{ 174 struct drm_device *dev = chan->dev; 175 struct nvc0_fifo_chan *fifoch; 176 177 nv_mask(dev, 0x003004 + (chan->id * 8), 0x00000001, 0x00000000); 178 nv_wr32(dev, 0x002634, chan->id); 179 if (!nv_wait(dev, 0x0002634, 0xffffffff, chan->id)) 180 NV_WARN(dev, "0x2634 != chid: 0x%08x\n", nv_rd32(dev, 0x2634)); 181 182 nvc0_fifo_playlist_update(dev); 183 184 nv_wr32(dev, 0x003000 + (chan->id * 8), 0x00000000); 185 186 if (chan->user) { 187 iounmap(chan->user); 188 chan->user = NULL; 189 } 190 191 fifoch = chan->fifo_priv; 192 chan->fifo_priv = NULL; 193 if (!fifoch) 194 return; 195 196 nouveau_gpuobj_ref(NULL, &fifoch->ramfc); 197 nouveau_gpuobj_ref(NULL, &fifoch->user); 198 kfree(fifoch); 199} 200 201int 202nvc0_fifo_load_context(struct nouveau_channel *chan) 203{ 204 return 0; 205} 206 207int 208nvc0_fifo_unload_context(struct drm_device *dev) 209{ 210 int i; 211 212 for (i = 0; i < 128; i++) { 213 if (!(nv_rd32(dev, 0x003004 + (i * 8)) & 1)) 214 continue; 215 216 nv_mask(dev, 0x003004 + (i * 8), 0x00000001, 0x00000000); 217 nv_wr32(dev, 0x002634, i); 218 if (!nv_wait(dev, 0x002634, 0xffffffff, i)) { 219 NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n", 220 i, nv_rd32(dev, 0x002634)); 221 return -EBUSY; 222 } 223 } 224 225 return 0; 226} 227 228static void 229nvc0_fifo_destroy(struct drm_device *dev) 230{ 231 struct drm_nouveau_private *dev_priv = dev->dev_private; 232 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 233 struct nvc0_fifo_priv *priv; 234 235 priv = pfifo->priv; 236 if (!priv) 237 return; 238 239 nouveau_vm_put(&priv->user_vma); 240 nouveau_gpuobj_ref(NULL, &priv->playlist[1]); 241 nouveau_gpuobj_ref(NULL, &priv->playlist[0]); 242 kfree(priv); 243} 244 245void 246nvc0_fifo_takedown(struct drm_device *dev) 247{ 248 nv_wr32(dev, 0x002140, 0x00000000); 249 nvc0_fifo_destroy(dev); 250} 251 252static int 253nvc0_fifo_create(struct drm_device *dev) 254{ 255 struct drm_nouveau_private *dev_priv = dev->dev_private; 256 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 257 struct nvc0_fifo_priv *priv; 258 int ret; 259 260 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 261 if (!priv) 262 return -ENOMEM; 263 pfifo->priv = priv; 264 265 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000, 0, 266 &priv->playlist[0]); 267 if (ret) 268 goto error; 269 270 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000, 0, 271 &priv->playlist[1]); 272 if (ret) 273 goto error; 274 275 ret = nouveau_vm_get(dev_priv->bar1_vm, pfifo->channels * 0x1000, 276 12, NV_MEM_ACCESS_RW, &priv->user_vma); 277 if (ret) 278 goto error; 279 280 nouveau_irq_register(dev, 8, nvc0_fifo_isr); 281 NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ 282 return 0; 283 284error: 285 nvc0_fifo_destroy(dev); 286 return ret; 287} 288 289int 290nvc0_fifo_init(struct drm_device *dev) 291{ 292 struct drm_nouveau_private *dev_priv = dev->dev_private; 293 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 294 struct nouveau_channel *chan; 295 struct nvc0_fifo_priv *priv; 296 int ret, i; 297 298 if (!pfifo->priv) { 299 ret = nvc0_fifo_create(dev); 300 if (ret) 301 return ret; 302 } 303 priv = pfifo->priv; 304 305 /* reset PFIFO, enable all available PSUBFIFO areas */ 306 nv_mask(dev, 0x000200, 0x00000100, 0x00000000); 307 nv_mask(dev, 0x000200, 0x00000100, 0x00000100); 308 nv_wr32(dev, 0x000204, 0xffffffff); 309 nv_wr32(dev, 0x002204, 0xffffffff); 310 311 priv->spoon_nr = hweight32(nv_rd32(dev, 0x002204)); 312 NV_DEBUG(dev, "PFIFO: %d subfifo(s)\n", priv->spoon_nr); 313 314 /* assign engines to subfifos */ 315 if (priv->spoon_nr >= 3) { 316 nv_wr32(dev, 0x002208, ~(1 << 0)); /* PGRAPH */ 317 nv_wr32(dev, 0x00220c, ~(1 << 1)); /* PVP */ 318 nv_wr32(dev, 0x002210, ~(1 << 1)); /* PPP */ 319 nv_wr32(dev, 0x002214, ~(1 << 1)); /* PBSP */ 320 nv_wr32(dev, 0x002218, ~(1 << 2)); /* PCE0 */ 321 nv_wr32(dev, 0x00221c, ~(1 << 1)); /* PCE1 */ 322 } 323 324 /* PSUBFIFO[n] */ 325 for (i = 0; i < priv->spoon_nr; i++) { 326 nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); 327 nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ 328 nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */ 329 } 330 331 nv_mask(dev, 0x002200, 0x00000001, 0x00000001); 332 nv_wr32(dev, 0x002254, 0x10000000 | priv->user_vma.offset >> 12); 333 334 nv_wr32(dev, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ 335 nv_wr32(dev, 0x002100, 0xffffffff); 336 nv_wr32(dev, 0x002140, 0xbfffffff); 337 338 /* restore PFIFO context table */ 339 for (i = 0; i < 128; i++) { 340 chan = dev_priv->channels.ptr[i]; 341 if (!chan || !chan->fifo_priv) 342 continue; 343 344 nv_wr32(dev, 0x003000 + (i * 8), 0xc0000000 | 345 (chan->ramin->vinst >> 12)); 346 nv_wr32(dev, 0x003004 + (i * 8), 0x001f0001); 347 } 348 nvc0_fifo_playlist_update(dev); 349 350 return 0; 351} 352 353struct nouveau_enum nvc0_fifo_fault_unit[] = { 354 { 0x00, "PGRAPH" }, 355 { 0x03, "PEEPHOLE" }, 356 { 0x04, "BAR1" }, 357 { 0x05, "BAR3" }, 358 { 0x07, "PFIFO" }, 359 { 0x10, "PBSP" }, 360 { 0x11, "PPPP" }, 361 { 0x13, "PCOUNTER" }, 362 { 0x14, "PVP" }, 363 { 0x15, "PCOPY0" }, 364 { 0x16, "PCOPY1" }, 365 { 0x17, "PDAEMON" }, 366 {} 367}; 368 369struct nouveau_enum nvc0_fifo_fault_reason[] = { 370 { 0x00, "PT_NOT_PRESENT" }, 371 { 0x01, "PT_TOO_SHORT" }, 372 { 0x02, "PAGE_NOT_PRESENT" }, 373 { 0x03, "VM_LIMIT_EXCEEDED" }, 374 { 0x04, "NO_CHANNEL" }, 375 { 0x05, "PAGE_SYSTEM_ONLY" }, 376 { 0x06, "PAGE_READ_ONLY" }, 377 { 0x0a, "COMPRESSED_SYSRAM" }, 378 { 0x0c, "INVALID_STORAGE_TYPE" }, 379 {} 380}; 381 382struct nouveau_enum nvc0_fifo_fault_hubclient[] = { 383 { 0x01, "PCOPY0" }, 384 { 0x02, "PCOPY1" }, 385 { 0x04, "DISPATCH" }, 386 { 0x05, "CTXCTL" }, 387 { 0x06, "PFIFO" }, 388 { 0x07, "BAR_READ" }, 389 { 0x08, "BAR_WRITE" }, 390 { 0x0b, "PVP" }, 391 { 0x0c, "PPPP" }, 392 { 0x0d, "PBSP" }, 393 { 0x11, "PCOUNTER" }, 394 { 0x12, "PDAEMON" }, 395 { 0x14, "CCACHE" }, 396 { 0x15, "CCACHE_POST" }, 397 {} 398}; 399 400struct nouveau_enum nvc0_fifo_fault_gpcclient[] = { 401 { 0x01, "TEX" }, 402 { 0x0c, "ESETUP" }, 403 { 0x0e, "CTXCTL" }, 404 { 0x0f, "PROP" }, 405 {} 406}; 407 408struct nouveau_bitfield nvc0_fifo_subfifo_intr[] = { 409/* { 0x00008000, "" } seen with null ib push */ 410 { 0x00200000, "ILLEGAL_MTHD" }, 411 { 0x00800000, "EMPTY_SUBC" }, 412 {} 413}; 414 415static void 416nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit) 417{ 418 u32 inst = nv_rd32(dev, 0x2800 + (unit * 0x10)); 419 u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10)); 420 u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10)); 421 u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10)); 422 u32 client = (stat & 0x00001f00) >> 8; 423 424 NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [", 425 (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); 426 nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); 427 printk("] from "); 428 nouveau_enum_print(nvc0_fifo_fault_unit, unit); 429 if (stat & 0x00000040) { 430 printk("/"); 431 nouveau_enum_print(nvc0_fifo_fault_hubclient, client); 432 } else { 433 printk("/GPC%d/", (stat & 0x1f000000) >> 24); 434 nouveau_enum_print(nvc0_fifo_fault_gpcclient, client); 435 } 436 printk(" on channel 0x%010llx\n", (u64)inst << 12); 437} 438 439static void 440nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) 441{ 442 u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000)); 443 u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000)); 444 u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000)); 445 u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f; 446 u32 subc = (addr & 0x00070000); 447 u32 mthd = (addr & 0x00003ffc); 448 449 NV_INFO(dev, "PSUBFIFO %d:", unit); 450 nouveau_bitfield_print(nvc0_fifo_subfifo_intr, stat); 451 NV_INFO(dev, "PSUBFIFO %d: ch %d subc %d mthd 0x%04x data 0x%08x\n", 452 unit, chid, subc, mthd, data); 453 454 nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008); 455 nv_wr32(dev, 0x040108 + (unit * 0x2000), stat); 456} 457 458static void 459nvc0_fifo_isr(struct drm_device *dev) 460{ 461 u32 stat = nv_rd32(dev, 0x002100); 462 463 if (stat & 0x00000100) { 464 NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); 465 nv_wr32(dev, 0x002100, 0x00000100); 466 stat &= ~0x00000100; 467 } 468 469 if (stat & 0x10000000) { 470 u32 units = nv_rd32(dev, 0x00259c); 471 u32 u = units; 472 473 while (u) { 474 int i = ffs(u) - 1; 475 nvc0_fifo_isr_vm_fault(dev, i); 476 u &= ~(1 << i); 477 } 478 479 nv_wr32(dev, 0x00259c, units); 480 stat &= ~0x10000000; 481 } 482 483 if (stat & 0x20000000) { 484 u32 units = nv_rd32(dev, 0x0025a0); 485 u32 u = units; 486 487 while (u) { 488 int i = ffs(u) - 1; 489 nvc0_fifo_isr_subfifo_intr(dev, i); 490 u &= ~(1 << i); 491 } 492 493 nv_wr32(dev, 0x0025a0, units); 494 stat &= ~0x20000000; 495 } 496 497 if (stat & 0x40000000) { 498 NV_INFO(dev, "PFIFO: unknown status 0x40000000\n"); 499 nv_mask(dev, 0x002a00, 0x00000000, 0x00000000); 500 stat &= ~0x40000000; 501 } 502 503 if (stat) { 504 NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat); 505 nv_wr32(dev, 0x002100, stat); 506 nv_wr32(dev, 0x002140, 0); 507 } 508} 509