usernv04.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * Copyright 2012 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. #define nv04_dmaobj(p) container_of((p), struct nv04_dmaobj, base)
  25. #include "user.h"
  26. #include <core/gpuobj.h>
  27. #include <subdev/fb.h>
  28. #include <subdev/mmu/nv04.h>
  29. #include <nvif/class.h>
  30. struct nv04_dmaobj {
  31. struct nvkm_dmaobj base;
  32. bool clone;
  33. u32 flags0;
  34. u32 flags2;
  35. };
  36. static int
  37. nv04_dmaobj_bind(struct nvkm_dmaobj *base, struct nvkm_gpuobj *parent,
  38. int align, struct nvkm_gpuobj **pgpuobj)
  39. {
  40. struct nv04_dmaobj *dmaobj = nv04_dmaobj(base);
  41. struct nvkm_device *device = dmaobj->base.dma->engine.subdev.device;
  42. u64 offset = dmaobj->base.start & 0xfffff000;
  43. u64 adjust = dmaobj->base.start & 0x00000fff;
  44. u32 length = dmaobj->base.limit - dmaobj->base.start;
  45. int ret;
  46. if (dmaobj->clone) {
  47. struct nv04_mmu *mmu = nv04_mmu(device->mmu);
  48. struct nvkm_memory *pgt = mmu->vm->pgt[0].mem[0];
  49. if (!dmaobj->base.start)
  50. return nvkm_gpuobj_wrap(pgt, pgpuobj);
  51. nvkm_kmap(pgt);
  52. offset = nvkm_ro32(pgt, 8 + (offset >> 10));
  53. offset &= 0xfffff000;
  54. nvkm_done(pgt);
  55. }
  56. ret = nvkm_gpuobj_new(device, 16, align, false, parent, pgpuobj);
  57. if (ret == 0) {
  58. nvkm_kmap(*pgpuobj);
  59. nvkm_wo32(*pgpuobj, 0x00, dmaobj->flags0 | (adjust << 20));
  60. nvkm_wo32(*pgpuobj, 0x04, length);
  61. nvkm_wo32(*pgpuobj, 0x08, dmaobj->flags2 | offset);
  62. nvkm_wo32(*pgpuobj, 0x0c, dmaobj->flags2 | offset);
  63. nvkm_done(*pgpuobj);
  64. }
  65. return ret;
  66. }
  67. static const struct nvkm_dmaobj_func
  68. nv04_dmaobj_func = {
  69. .bind = nv04_dmaobj_bind,
  70. };
  71. int
  72. nv04_dmaobj_new(struct nvkm_dma *dma, const struct nvkm_oclass *oclass,
  73. void *data, u32 size, struct nvkm_dmaobj **pdmaobj)
  74. {
  75. struct nvkm_device *device = dma->engine.subdev.device;
  76. struct nv04_dmaobj *dmaobj;
  77. int ret;
  78. if (!(dmaobj = kzalloc(sizeof(*dmaobj), GFP_KERNEL)))
  79. return -ENOMEM;
  80. *pdmaobj = &dmaobj->base;
  81. ret = nvkm_dmaobj_ctor(&nv04_dmaobj_func, dma, oclass,
  82. &data, &size, &dmaobj->base);
  83. if (ret)
  84. return ret;
  85. if (dmaobj->base.target == NV_MEM_TARGET_VM) {
  86. if (device->mmu->func == &nv04_mmu)
  87. dmaobj->clone = true;
  88. dmaobj->base.target = NV_MEM_TARGET_PCI;
  89. dmaobj->base.access = NV_MEM_ACCESS_RW;
  90. }
  91. dmaobj->flags0 = oclass->base.oclass;
  92. switch (dmaobj->base.target) {
  93. case NV_MEM_TARGET_VRAM:
  94. dmaobj->flags0 |= 0x00003000;
  95. break;
  96. case NV_MEM_TARGET_PCI:
  97. dmaobj->flags0 |= 0x00023000;
  98. break;
  99. case NV_MEM_TARGET_PCI_NOSNOOP:
  100. dmaobj->flags0 |= 0x00033000;
  101. break;
  102. default:
  103. return -EINVAL;
  104. }
  105. switch (dmaobj->base.access) {
  106. case NV_MEM_ACCESS_RO:
  107. dmaobj->flags0 |= 0x00004000;
  108. break;
  109. case NV_MEM_ACCESS_WO:
  110. dmaobj->flags0 |= 0x00008000;
  111. case NV_MEM_ACCESS_RW:
  112. dmaobj->flags2 |= 0x00000002;
  113. break;
  114. default:
  115. return -EINVAL;
  116. }
  117. return 0;
  118. }