nv50_fb.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #include "drmP.h"
  2. #include "drm.h"
  3. #include "nouveau_drv.h"
  4. #include "nouveau_drm.h"
  5. struct nv50_fb_priv {
  6. struct page *r100c08_page;
  7. dma_addr_t r100c08;
  8. };
  9. static void
  10. nv50_fb_destroy(struct drm_device *dev)
  11. {
  12. struct drm_nouveau_private *dev_priv = dev->dev_private;
  13. struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
  14. struct nv50_fb_priv *priv = pfb->priv;
  15. if (drm_mm_initialized(&pfb->tag_heap))
  16. drm_mm_takedown(&pfb->tag_heap);
  17. if (priv->r100c08_page) {
  18. pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE,
  19. PCI_DMA_BIDIRECTIONAL);
  20. __free_page(priv->r100c08_page);
  21. }
  22. kfree(priv);
  23. pfb->priv = NULL;
  24. }
  25. static int
  26. nv50_fb_create(struct drm_device *dev)
  27. {
  28. struct drm_nouveau_private *dev_priv = dev->dev_private;
  29. struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
  30. struct nv50_fb_priv *priv;
  31. u32 tagmem;
  32. int ret;
  33. priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  34. if (!priv)
  35. return -ENOMEM;
  36. pfb->priv = priv;
  37. priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
  38. if (!priv->r100c08_page) {
  39. nv50_fb_destroy(dev);
  40. return -ENOMEM;
  41. }
  42. priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0,
  43. PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
  44. if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) {
  45. nv50_fb_destroy(dev);
  46. return -EFAULT;
  47. }
  48. tagmem = nv_rd32(dev, 0x100320);
  49. NV_DEBUG(dev, "%d tags available\n", tagmem);
  50. ret = drm_mm_init(&pfb->tag_heap, 0, tagmem);
  51. if (ret) {
  52. nv50_fb_destroy(dev);
  53. return ret;
  54. }
  55. return 0;
  56. }
  57. int
  58. nv50_fb_init(struct drm_device *dev)
  59. {
  60. struct drm_nouveau_private *dev_priv = dev->dev_private;
  61. struct nv50_fb_priv *priv;
  62. int ret;
  63. if (!dev_priv->engine.fb.priv) {
  64. ret = nv50_fb_create(dev);
  65. if (ret)
  66. return ret;
  67. }
  68. priv = dev_priv->engine.fb.priv;
  69. /* Not a clue what this is exactly. Without pointing it at a
  70. * scratch page, VRAM->GART blits with M2MF (as in DDX DFS)
  71. * cause IOMMU "read from address 0" errors (rh#561267)
  72. */
  73. nv_wr32(dev, 0x100c08, priv->r100c08 >> 8);
  74. /* This is needed to get meaningful information from 100c90
  75. * on traps. No idea what these values mean exactly. */
  76. switch (dev_priv->chipset) {
  77. case 0x50:
  78. nv_wr32(dev, 0x100c90, 0x000707ff);
  79. break;
  80. case 0xa3:
  81. case 0xa5:
  82. case 0xa8:
  83. nv_wr32(dev, 0x100c90, 0x000d0fff);
  84. break;
  85. case 0xaf:
  86. nv_wr32(dev, 0x100c90, 0x089d1fff);
  87. break;
  88. default:
  89. nv_wr32(dev, 0x100c90, 0x001d07ff);
  90. break;
  91. }
  92. return 0;
  93. }
  94. void
  95. nv50_fb_takedown(struct drm_device *dev)
  96. {
  97. nv50_fb_destroy(dev);
  98. }
  99. void
  100. nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name)
  101. {
  102. struct drm_nouveau_private *dev_priv = dev->dev_private;
  103. unsigned long flags;
  104. u32 trap[6], idx, chinst;
  105. int i, ch;
  106. idx = nv_rd32(dev, 0x100c90);
  107. if (!(idx & 0x80000000))
  108. return;
  109. idx &= 0x00ffffff;
  110. for (i = 0; i < 6; i++) {
  111. nv_wr32(dev, 0x100c90, idx | i << 24);
  112. trap[i] = nv_rd32(dev, 0x100c94);
  113. }
  114. nv_wr32(dev, 0x100c90, idx | 0x80000000);
  115. if (!display)
  116. return;
  117. chinst = (trap[2] << 16) | trap[1];
  118. spin_lock_irqsave(&dev_priv->channels.lock, flags);
  119. for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) {
  120. struct nouveau_channel *chan = dev_priv->channels.ptr[ch];
  121. if (!chan || !chan->ramin)
  122. continue;
  123. if (chinst == chan->ramin->vinst >> 12)
  124. break;
  125. }
  126. spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
  127. NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x "
  128. "channel %d (0x%08x)\n",
  129. name, (trap[5] & 0x100 ? "read" : "write"),
  130. trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff,
  131. trap[0], ch, chinst);
  132. }