gem.c 10 KB

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