gem.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * psb GEM interface
  4. *
  5. * Copyright (c) 2011, Intel Corporation.
  6. *
  7. * Authors: Alan Cox
  8. *
  9. * TODO:
  10. * - we need to work out if the MMU is relevant (eg for
  11. * accelerated operations on a GEM object)
  12. */
  13. #include <linux/pagemap.h>
  14. #include <asm/set_memory.h>
  15. #include <drm/drm.h>
  16. #include <drm/drm_vma_manager.h>
  17. #include "gem.h"
  18. #include "psb_drv.h"
  19. /*
  20. * PSB GEM object
  21. */
  22. int psb_gem_pin(struct psb_gem_object *pobj)
  23. {
  24. struct drm_gem_object *obj = &pobj->base;
  25. struct drm_device *dev = obj->dev;
  26. struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
  27. u32 gpu_base = dev_priv->gtt.gatt_start;
  28. struct page **pages;
  29. unsigned int npages;
  30. int ret;
  31. ret = dma_resv_lock(obj->resv, NULL);
  32. if (drm_WARN_ONCE(dev, ret, "dma_resv_lock() failed, ret=%d\n", ret))
  33. return ret;
  34. if (pobj->in_gart || pobj->stolen)
  35. goto out; /* already mapped */
  36. pages = drm_gem_get_pages(obj);
  37. if (IS_ERR(pages)) {
  38. ret = PTR_ERR(pages);
  39. goto err_dma_resv_unlock;
  40. }
  41. npages = obj->size / PAGE_SIZE;
  42. set_pages_array_wc(pages, npages);
  43. psb_gtt_insert_pages(dev_priv, &pobj->resource, pages);
  44. psb_mmu_insert_pages(psb_mmu_get_default_pd(dev_priv->mmu), pages,
  45. (gpu_base + pobj->offset), npages, 0, 0,
  46. PSB_MMU_CACHED_MEMORY);
  47. pobj->pages = pages;
  48. out:
  49. ++pobj->in_gart;
  50. dma_resv_unlock(obj->resv);
  51. return 0;
  52. err_dma_resv_unlock:
  53. dma_resv_unlock(obj->resv);
  54. return ret;
  55. }
  56. void psb_gem_unpin(struct psb_gem_object *pobj)
  57. {
  58. struct drm_gem_object *obj = &pobj->base;
  59. struct drm_device *dev = obj->dev;
  60. struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
  61. u32 gpu_base = dev_priv->gtt.gatt_start;
  62. unsigned long npages;
  63. int ret;
  64. ret = dma_resv_lock(obj->resv, NULL);
  65. if (drm_WARN_ONCE(dev, ret, "dma_resv_lock() failed, ret=%d\n", ret))
  66. return;
  67. WARN_ON(!pobj->in_gart);
  68. --pobj->in_gart;
  69. if (pobj->in_gart || pobj->stolen)
  70. goto out;
  71. npages = obj->size / PAGE_SIZE;
  72. psb_mmu_remove_pages(psb_mmu_get_default_pd(dev_priv->mmu),
  73. (gpu_base + pobj->offset), npages, 0, 0);
  74. psb_gtt_remove_pages(dev_priv, &pobj->resource);
  75. /* Reset caching flags */
  76. set_pages_array_wb(pobj->pages, npages);
  77. drm_gem_put_pages(obj, pobj->pages, true, false);
  78. pobj->pages = NULL;
  79. out:
  80. dma_resv_unlock(obj->resv);
  81. }
  82. static vm_fault_t psb_gem_fault(struct vm_fault *vmf);
  83. static void psb_gem_free_object(struct drm_gem_object *obj)
  84. {
  85. struct psb_gem_object *pobj = to_psb_gem_object(obj);
  86. /* Undo the mmap pin if we are destroying the object */
  87. if (pobj->mmapping)
  88. psb_gem_unpin(pobj);
  89. drm_gem_object_release(obj);
  90. WARN_ON(pobj->in_gart && !pobj->stolen);
  91. release_resource(&pobj->resource);
  92. kfree(pobj);
  93. }
  94. static const struct vm_operations_struct psb_gem_vm_ops = {
  95. .fault = psb_gem_fault,
  96. .open = drm_gem_vm_open,
  97. .close = drm_gem_vm_close,
  98. };
  99. static const struct drm_gem_object_funcs psb_gem_object_funcs = {
  100. .free = psb_gem_free_object,
  101. .vm_ops = &psb_gem_vm_ops,
  102. };
  103. struct psb_gem_object *
  104. psb_gem_create(struct drm_device *dev, u64 size, const char *name, bool stolen, u32 align)
  105. {
  106. struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
  107. struct psb_gem_object *pobj;
  108. struct drm_gem_object *obj;
  109. int ret;
  110. size = roundup(size, PAGE_SIZE);
  111. pobj = kzalloc(sizeof(*pobj), GFP_KERNEL);
  112. if (!pobj)
  113. return ERR_PTR(-ENOMEM);
  114. obj = &pobj->base;
  115. /* GTT resource */
  116. ret = psb_gtt_allocate_resource(dev_priv, &pobj->resource, name, size, align, stolen,
  117. &pobj->offset);
  118. if (ret)
  119. goto err_kfree;
  120. if (stolen) {
  121. pobj->stolen = true;
  122. pobj->in_gart = 1;
  123. }
  124. /* GEM object */
  125. obj->funcs = &psb_gem_object_funcs;
  126. if (stolen) {
  127. drm_gem_private_object_init(dev, obj, size);
  128. } else {
  129. ret = drm_gem_object_init(dev, obj, size);
  130. if (ret)
  131. goto err_release_resource;
  132. /* Limit the object to 32-bit mappings */
  133. mapping_set_gfp_mask(obj->filp->f_mapping, GFP_KERNEL | __GFP_DMA32);
  134. }
  135. return pobj;
  136. err_release_resource:
  137. release_resource(&pobj->resource);
  138. err_kfree:
  139. kfree(pobj);
  140. return ERR_PTR(ret);
  141. }
  142. /**
  143. * psb_gem_dumb_create - create a dumb buffer
  144. * @file: our client file
  145. * @dev: our device
  146. * @args: the requested arguments copied from userspace
  147. *
  148. * Allocate a buffer suitable for use for a frame buffer of the
  149. * form described by user space. Give userspace a handle by which
  150. * to reference it.
  151. */
  152. int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
  153. struct drm_mode_create_dumb *args)
  154. {
  155. size_t pitch, size;
  156. struct psb_gem_object *pobj;
  157. struct drm_gem_object *obj;
  158. u32 handle;
  159. int ret;
  160. pitch = args->width * DIV_ROUND_UP(args->bpp, 8);
  161. pitch = ALIGN(pitch, 64);
  162. size = pitch * args->height;
  163. size = roundup(size, PAGE_SIZE);
  164. if (!size)
  165. return -EINVAL;
  166. pobj = psb_gem_create(dev, size, "gem", false, PAGE_SIZE);
  167. if (IS_ERR(pobj))
  168. return PTR_ERR(pobj);
  169. obj = &pobj->base;
  170. ret = drm_gem_handle_create(file, obj, &handle);
  171. if (ret)
  172. goto err_drm_gem_object_put;
  173. drm_gem_object_put(obj);
  174. args->pitch = pitch;
  175. args->size = size;
  176. args->handle = handle;
  177. return 0;
  178. err_drm_gem_object_put:
  179. drm_gem_object_put(obj);
  180. return ret;
  181. }
  182. /**
  183. * psb_gem_fault - pagefault handler for GEM objects
  184. * @vmf: fault detail
  185. *
  186. * Invoked when a fault occurs on an mmap of a GEM managed area. GEM
  187. * does most of the work for us including the actual map/unmap calls
  188. * but we need to do the actual page work.
  189. *
  190. * This code eventually needs to handle faulting objects in and out
  191. * of the GTT and repacking it when we run out of space. We can put
  192. * that off for now and for our simple uses
  193. *
  194. * The VMA was set up by GEM. In doing so it also ensured that the
  195. * vma->vm_private_data points to the GEM object that is backing this
  196. * mapping.
  197. */
  198. static vm_fault_t psb_gem_fault(struct vm_fault *vmf)
  199. {
  200. struct vm_area_struct *vma = vmf->vma;
  201. struct drm_gem_object *obj;
  202. struct psb_gem_object *pobj;
  203. int err;
  204. vm_fault_t ret;
  205. unsigned long pfn;
  206. pgoff_t page_offset;
  207. struct drm_device *dev;
  208. struct drm_psb_private *dev_priv;
  209. obj = vma->vm_private_data; /* GEM object */
  210. dev = obj->dev;
  211. dev_priv = to_drm_psb_private(dev);
  212. pobj = to_psb_gem_object(obj);
  213. /* Make sure we don't parallel update on a fault, nor move or remove
  214. something from beneath our feet */
  215. mutex_lock(&dev_priv->mmap_mutex);
  216. /* For now the mmap pins the object and it stays pinned. As things
  217. stand that will do us no harm */
  218. if (pobj->mmapping == 0) {
  219. err = psb_gem_pin(pobj);
  220. if (err < 0) {
  221. dev_err(dev->dev, "gma500: pin failed: %d\n", err);
  222. ret = vmf_error(err);
  223. goto fail;
  224. }
  225. pobj->mmapping = 1;
  226. }
  227. /* Page relative to the VMA start - we must calculate this ourselves
  228. because vmf->pgoff is the fake GEM offset */
  229. page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
  230. /* CPU view of the page, don't go via the GART for CPU writes */
  231. if (pobj->stolen)
  232. pfn = (dev_priv->stolen_base + pobj->offset) >> PAGE_SHIFT;
  233. else
  234. pfn = page_to_pfn(pobj->pages[page_offset]);
  235. ret = vmf_insert_pfn(vma, vmf->address, pfn);
  236. fail:
  237. mutex_unlock(&dev_priv->mmap_mutex);
  238. return ret;
  239. }
  240. /*
  241. * Memory management
  242. */
  243. /* Insert vram stolen pages into the GTT. */
  244. static void psb_gem_mm_populate_stolen(struct drm_psb_private *pdev)
  245. {
  246. struct drm_device *dev = &pdev->dev;
  247. unsigned int pfn_base;
  248. unsigned int i, num_pages;
  249. uint32_t pte;
  250. pfn_base = pdev->stolen_base >> PAGE_SHIFT;
  251. num_pages = pdev->vram_stolen_size >> PAGE_SHIFT;
  252. drm_dbg(dev, "Set up %u stolen pages starting at 0x%08x, GTT offset %dK\n",
  253. num_pages, pfn_base << PAGE_SHIFT, 0);
  254. for (i = 0; i < num_pages; ++i) {
  255. pte = psb_gtt_mask_pte(pfn_base + i, PSB_MMU_CACHED_MEMORY);
  256. iowrite32(pte, pdev->gtt_map + i);
  257. }
  258. (void)ioread32(pdev->gtt_map + i - 1);
  259. }
  260. int psb_gem_mm_init(struct drm_device *dev)
  261. {
  262. struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
  263. struct pci_dev *pdev = to_pci_dev(dev->dev);
  264. unsigned long stolen_size, vram_stolen_size;
  265. struct psb_gtt *pg;
  266. int ret;
  267. mutex_init(&dev_priv->mmap_mutex);
  268. pg = &dev_priv->gtt;
  269. pci_read_config_dword(pdev, PSB_BSM, &dev_priv->stolen_base);
  270. vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE;
  271. stolen_size = vram_stolen_size;
  272. dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n",
  273. dev_priv->stolen_base, vram_stolen_size / 1024);
  274. pg->stolen_size = stolen_size;
  275. dev_priv->vram_stolen_size = vram_stolen_size;
  276. dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
  277. if (!dev_priv->vram_addr) {
  278. dev_err(dev->dev, "Failure to map stolen base.\n");
  279. ret = -ENOMEM;
  280. goto err_mutex_destroy;
  281. }
  282. psb_gem_mm_populate_stolen(dev_priv);
  283. return 0;
  284. err_mutex_destroy:
  285. mutex_destroy(&dev_priv->mmap_mutex);
  286. return ret;
  287. }
  288. void psb_gem_mm_fini(struct drm_device *dev)
  289. {
  290. struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
  291. iounmap(dev_priv->vram_addr);
  292. mutex_destroy(&dev_priv->mmap_mutex);
  293. }
  294. /* Re-insert all pinned GEM objects into GTT. */
  295. static void psb_gem_mm_populate_resources(struct drm_psb_private *pdev)
  296. {
  297. unsigned int restored = 0, total = 0, size = 0;
  298. struct resource *r = pdev->gtt_mem->child;
  299. struct drm_device *dev = &pdev->dev;
  300. struct psb_gem_object *pobj;
  301. while (r) {
  302. /*
  303. * TODO: GTT restoration needs a refactoring, so that we don't have to touch
  304. * struct psb_gem_object here. The type represents a GEM object and is
  305. * not related to the GTT itself.
  306. */
  307. pobj = container_of(r, struct psb_gem_object, resource);
  308. if (pobj->pages) {
  309. psb_gtt_insert_pages(pdev, &pobj->resource, pobj->pages);
  310. size += resource_size(&pobj->resource);
  311. ++restored;
  312. }
  313. r = r->sibling;
  314. ++total;
  315. }
  316. drm_dbg(dev, "Restored %u of %u gtt ranges (%u KB)", restored, total, (size / 1024));
  317. }
  318. int psb_gem_mm_resume(struct drm_device *dev)
  319. {
  320. struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
  321. struct pci_dev *pdev = to_pci_dev(dev->dev);
  322. unsigned long stolen_size, vram_stolen_size;
  323. struct psb_gtt *pg;
  324. pg = &dev_priv->gtt;
  325. pci_read_config_dword(pdev, PSB_BSM, &dev_priv->stolen_base);
  326. vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE;
  327. stolen_size = vram_stolen_size;
  328. dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n", dev_priv->stolen_base,
  329. vram_stolen_size / 1024);
  330. if (stolen_size != pg->stolen_size) {
  331. dev_err(dev->dev, "GTT resume error.\n");
  332. return -EINVAL;
  333. }
  334. psb_gem_mm_populate_stolen(dev_priv);
  335. psb_gem_mm_populate_resources(dev_priv);
  336. return 0;
  337. }