nvc0_instmem.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. #include "drmP.h"
  25. #include "nouveau_drv.h"
  26. #include "nouveau_vm.h"
  27. struct nvc0_instmem_priv {
  28. struct nouveau_gpuobj *bar1_pgd;
  29. struct nouveau_channel *bar1;
  30. struct nouveau_gpuobj *bar3_pgd;
  31. struct nouveau_channel *bar3;
  32. struct nouveau_gpuobj *chan_pgd;
  33. };
  34. int
  35. nvc0_instmem_suspend(struct drm_device *dev)
  36. {
  37. struct drm_nouveau_private *dev_priv = dev->dev_private;
  38. dev_priv->ramin_available = false;
  39. return 0;
  40. }
  41. void
  42. nvc0_instmem_resume(struct drm_device *dev)
  43. {
  44. struct drm_nouveau_private *dev_priv = dev->dev_private;
  45. struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv;
  46. nv_mask(dev, 0x100c80, 0x00000001, 0x00000000);
  47. nv_wr32(dev, 0x001704, 0x80000000 | priv->bar1->ramin->vinst >> 12);
  48. nv_wr32(dev, 0x001714, 0xc0000000 | priv->bar3->ramin->vinst >> 12);
  49. dev_priv->ramin_available = true;
  50. }
  51. static void
  52. nvc0_channel_del(struct nouveau_channel **pchan)
  53. {
  54. struct nouveau_channel *chan;
  55. chan = *pchan;
  56. *pchan = NULL;
  57. if (!chan)
  58. return;
  59. nouveau_vm_ref(NULL, &chan->vm, NULL);
  60. if (chan->ramin_heap.free_stack.next)
  61. drm_mm_takedown(&chan->ramin_heap);
  62. nouveau_gpuobj_ref(NULL, &chan->ramin);
  63. kfree(chan);
  64. }
  65. static int
  66. nvc0_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm,
  67. struct nouveau_channel **pchan,
  68. struct nouveau_gpuobj *pgd, u64 vm_size)
  69. {
  70. struct nouveau_channel *chan;
  71. int ret;
  72. chan = kzalloc(sizeof(*chan), GFP_KERNEL);
  73. if (!chan)
  74. return -ENOMEM;
  75. chan->dev = dev;
  76. ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin);
  77. if (ret) {
  78. nvc0_channel_del(&chan);
  79. return ret;
  80. }
  81. ret = drm_mm_init(&chan->ramin_heap, 0x1000, size - 0x1000);
  82. if (ret) {
  83. nvc0_channel_del(&chan);
  84. return ret;
  85. }
  86. ret = nouveau_vm_ref(vm, &chan->vm, NULL);
  87. if (ret) {
  88. nvc0_channel_del(&chan);
  89. return ret;
  90. }
  91. nv_wo32(chan->ramin, 0x0200, lower_32_bits(pgd->vinst));
  92. nv_wo32(chan->ramin, 0x0204, upper_32_bits(pgd->vinst));
  93. nv_wo32(chan->ramin, 0x0208, lower_32_bits(vm_size - 1));
  94. nv_wo32(chan->ramin, 0x020c, upper_32_bits(vm_size - 1));
  95. *pchan = chan;
  96. return 0;
  97. }
  98. int
  99. nvc0_instmem_init(struct drm_device *dev)
  100. {
  101. struct drm_nouveau_private *dev_priv = dev->dev_private;
  102. struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
  103. struct pci_dev *pdev = dev->pdev;
  104. struct nvc0_instmem_priv *priv;
  105. struct nouveau_vm *vm = NULL;
  106. int ret;
  107. priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  108. if (!priv)
  109. return -ENOMEM;
  110. pinstmem->priv = priv;
  111. /* BAR3 VM */
  112. ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 3), 0,
  113. &dev_priv->bar3_vm);
  114. if (ret)
  115. goto error;
  116. ret = nouveau_gpuobj_new(dev, NULL,
  117. (pci_resource_len(pdev, 3) >> 12) * 8, 0,
  118. NVOBJ_FLAG_DONT_MAP |
  119. NVOBJ_FLAG_ZERO_ALLOC,
  120. &dev_priv->bar3_vm->pgt[0].obj[0]);
  121. if (ret)
  122. goto error;
  123. dev_priv->bar3_vm->pgt[0].refcount[0] = 1;
  124. nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]);
  125. ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096,
  126. NVOBJ_FLAG_ZERO_ALLOC, &priv->bar3_pgd);
  127. if (ret)
  128. goto error;
  129. ret = nouveau_vm_ref(dev_priv->bar3_vm, &vm, priv->bar3_pgd);
  130. if (ret)
  131. goto error;
  132. nouveau_vm_ref(NULL, &vm, NULL);
  133. ret = nvc0_channel_new(dev, 8192, dev_priv->bar3_vm, &priv->bar3,
  134. priv->bar3_pgd, pci_resource_len(dev->pdev, 3));
  135. if (ret)
  136. goto error;
  137. /* BAR1 VM */
  138. ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 1), 0, &vm);
  139. if (ret)
  140. goto error;
  141. ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096,
  142. NVOBJ_FLAG_ZERO_ALLOC, &priv->bar1_pgd);
  143. if (ret)
  144. goto error;
  145. ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, priv->bar1_pgd);
  146. if (ret)
  147. goto error;
  148. nouveau_vm_ref(NULL, &vm, NULL);
  149. ret = nvc0_channel_new(dev, 8192, dev_priv->bar1_vm, &priv->bar1,
  150. priv->bar1_pgd, pci_resource_len(dev->pdev, 1));
  151. if (ret)
  152. goto error;
  153. /* channel vm */
  154. ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, &vm);
  155. if (ret)
  156. goto error;
  157. ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, 0, &priv->chan_pgd);
  158. if (ret)
  159. goto error;
  160. nouveau_vm_ref(vm, &dev_priv->chan_vm, priv->chan_pgd);
  161. nouveau_vm_ref(NULL, &vm, NULL);
  162. nvc0_instmem_resume(dev);
  163. return 0;
  164. error:
  165. nvc0_instmem_takedown(dev);
  166. return ret;
  167. }
  168. void
  169. nvc0_instmem_takedown(struct drm_device *dev)
  170. {
  171. struct drm_nouveau_private *dev_priv = dev->dev_private;
  172. struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv;
  173. struct nouveau_vm *vm = NULL;
  174. nvc0_instmem_suspend(dev);
  175. nv_wr32(dev, 0x1704, 0x00000000);
  176. nv_wr32(dev, 0x1714, 0x00000000);
  177. nouveau_vm_ref(NULL, &dev_priv->chan_vm, priv->chan_pgd);
  178. nouveau_gpuobj_ref(NULL, &priv->chan_pgd);
  179. nvc0_channel_del(&priv->bar1);
  180. nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd);
  181. nouveau_gpuobj_ref(NULL, &priv->bar1_pgd);
  182. nvc0_channel_del(&priv->bar3);
  183. nouveau_vm_ref(dev_priv->bar3_vm, &vm, NULL);
  184. nouveau_vm_ref(NULL, &vm, priv->bar3_pgd);
  185. nouveau_gpuobj_ref(NULL, &priv->bar3_pgd);
  186. nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]);
  187. nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL);
  188. dev_priv->engine.instmem.priv = NULL;
  189. kfree(priv);
  190. }