gtt.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /*
  2. * Copyright (c) 2007, Intel Corporation.
  3. * All Rights Reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms and conditions of the GNU General Public License,
  7. * version 2, as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  17. *
  18. * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
  19. * Alan Cox <alan@linux.intel.com>
  20. */
  21. #include <drm/drmP.h>
  22. #include "psb_drv.h"
  23. /*
  24. * GTT resource allocator - manage page mappings in GTT space
  25. */
  26. /**
  27. * psb_gtt_mask_pte - generate GTT pte entry
  28. * @pfn: page number to encode
  29. * @type: type of memory in the GTT
  30. *
  31. * Set the GTT entry for the appropriate memory type.
  32. */
  33. static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
  34. {
  35. uint32_t mask = PSB_PTE_VALID;
  36. if (type & PSB_MMU_CACHED_MEMORY)
  37. mask |= PSB_PTE_CACHED;
  38. if (type & PSB_MMU_RO_MEMORY)
  39. mask |= PSB_PTE_RO;
  40. if (type & PSB_MMU_WO_MEMORY)
  41. mask |= PSB_PTE_WO;
  42. return (pfn << PAGE_SHIFT) | mask;
  43. }
  44. /**
  45. * psb_gtt_entry - find the GTT entries for a gtt_range
  46. * @dev: our DRM device
  47. * @r: our GTT range
  48. *
  49. * Given a gtt_range object return the GTT offset of the page table
  50. * entries for this gtt_range
  51. */
  52. u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
  53. {
  54. struct drm_psb_private *dev_priv = dev->dev_private;
  55. unsigned long offset;
  56. offset = r->resource.start - dev_priv->gtt_mem->start;
  57. return dev_priv->gtt_map + (offset >> PAGE_SHIFT);
  58. }
  59. /**
  60. * psb_gtt_insert - put an object into the GTT
  61. * @dev: our DRM device
  62. * @r: our GTT range
  63. *
  64. * Take our preallocated GTT range and insert the GEM object into
  65. * the GTT.
  66. *
  67. * FIXME: gtt lock ?
  68. */
  69. static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
  70. {
  71. u32 *gtt_slot, pte;
  72. struct page **pages;
  73. int i;
  74. if (r->pages == NULL) {
  75. WARN_ON(1);
  76. return -EINVAL;
  77. }
  78. WARN_ON(r->stolen); /* refcount these maybe ? */
  79. gtt_slot = psb_gtt_entry(dev, r);
  80. pages = r->pages;
  81. /* Make sure changes are visible to the GPU */
  82. set_pages_array_uc(pages, r->npage);
  83. /* Write our page entries into the GTT itself */
  84. for (i = 0; i < r->npage; i++) {
  85. pte = psb_gtt_mask_pte(page_to_pfn(*pages++), 0/*type*/);
  86. iowrite32(pte, gtt_slot++);
  87. }
  88. /* Make sure all the entries are set before we return */
  89. ioread32(gtt_slot - 1);
  90. return 0;
  91. }
  92. /**
  93. * psb_gtt_remove - remove an object from the GTT
  94. * @dev: our DRM device
  95. * @r: our GTT range
  96. *
  97. * Remove a preallocated GTT range from the GTT. Overwrite all the
  98. * page table entries with the dummy page
  99. */
  100. static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
  101. {
  102. struct drm_psb_private *dev_priv = dev->dev_private;
  103. u32 *gtt_slot, pte;
  104. int i;
  105. WARN_ON(r->stolen);
  106. gtt_slot = psb_gtt_entry(dev, r);
  107. pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);
  108. for (i = 0; i < r->npage; i++)
  109. iowrite32(pte, gtt_slot++);
  110. ioread32(gtt_slot - 1);
  111. set_pages_array_wb(r->pages, r->npage);
  112. }
  113. /**
  114. * psb_gtt_attach_pages - attach and pin GEM pages
  115. * @gt: the gtt range
  116. *
  117. * Pin and build an in kernel list of the pages that back our GEM object.
  118. * While we hold this the pages cannot be swapped out
  119. */
  120. static int psb_gtt_attach_pages(struct gtt_range *gt)
  121. {
  122. struct inode *inode;
  123. struct address_space *mapping;
  124. int i;
  125. struct page *p;
  126. int pages = gt->gem.size / PAGE_SIZE;
  127. WARN_ON(gt->pages);
  128. /* This is the shared memory object that backs the GEM resource */
  129. inode = gt->gem.filp->f_path.dentry->d_inode;
  130. mapping = inode->i_mapping;
  131. gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL);
  132. if (gt->pages == NULL)
  133. return -ENOMEM;
  134. gt->npage = pages;
  135. for (i = 0; i < pages; i++) {
  136. /* FIXME: review flags later */
  137. p = read_cache_page_gfp(mapping, i,
  138. __GFP_COLD | GFP_KERNEL);
  139. if (IS_ERR(p))
  140. goto err;
  141. gt->pages[i] = p;
  142. }
  143. return 0;
  144. err:
  145. while (i--)
  146. page_cache_release(gt->pages[i]);
  147. kfree(gt->pages);
  148. gt->pages = NULL;
  149. return PTR_ERR(p);
  150. }
  151. /**
  152. * psb_gtt_detach_pages - attach and pin GEM pages
  153. * @gt: the gtt range
  154. *
  155. * Undo the effect of psb_gtt_attach_pages. At this point the pages
  156. * must have been removed from the GTT as they could now be paged out
  157. * and move bus address.
  158. */
  159. static void psb_gtt_detach_pages(struct gtt_range *gt)
  160. {
  161. int i;
  162. for (i = 0; i < gt->npage; i++) {
  163. /* FIXME: do we need to force dirty */
  164. set_page_dirty(gt->pages[i]);
  165. page_cache_release(gt->pages[i]);
  166. }
  167. kfree(gt->pages);
  168. gt->pages = NULL;
  169. }
  170. /**
  171. * psb_gtt_pin - pin pages into the GTT
  172. * @gt: range to pin
  173. *
  174. * Pin a set of pages into the GTT. The pins are refcounted so that
  175. * multiple pins need multiple unpins to undo.
  176. *
  177. * Non GEM backed objects treat this as a no-op as they are always GTT
  178. * backed objects.
  179. */
  180. int psb_gtt_pin(struct gtt_range *gt)
  181. {
  182. int ret = 0;
  183. struct drm_device *dev = gt->gem.dev;
  184. struct drm_psb_private *dev_priv = dev->dev_private;
  185. mutex_lock(&dev_priv->gtt_mutex);
  186. if (gt->in_gart == 0 && gt->stolen == 0) {
  187. ret = psb_gtt_attach_pages(gt);
  188. if (ret < 0)
  189. goto out;
  190. ret = psb_gtt_insert(dev, gt);
  191. if (ret < 0) {
  192. psb_gtt_detach_pages(gt);
  193. goto out;
  194. }
  195. }
  196. gt->in_gart++;
  197. out:
  198. mutex_unlock(&dev_priv->gtt_mutex);
  199. return ret;
  200. }
  201. /**
  202. * psb_gtt_unpin - Drop a GTT pin requirement
  203. * @gt: range to pin
  204. *
  205. * Undoes the effect of psb_gtt_pin. On the last drop the GEM object
  206. * will be removed from the GTT which will also drop the page references
  207. * and allow the VM to clean up or page stuff.
  208. *
  209. * Non GEM backed objects treat this as a no-op as they are always GTT
  210. * backed objects.
  211. */
  212. void psb_gtt_unpin(struct gtt_range *gt)
  213. {
  214. struct drm_device *dev = gt->gem.dev;
  215. struct drm_psb_private *dev_priv = dev->dev_private;
  216. mutex_lock(&dev_priv->gtt_mutex);
  217. WARN_ON(!gt->in_gart);
  218. gt->in_gart--;
  219. if (gt->in_gart == 0 && gt->stolen == 0) {
  220. psb_gtt_remove(dev, gt);
  221. psb_gtt_detach_pages(gt);
  222. }
  223. mutex_unlock(&dev_priv->gtt_mutex);
  224. }
  225. /*
  226. * GTT resource allocator - allocate and manage GTT address space
  227. */
  228. /**
  229. * psb_gtt_alloc_range - allocate GTT address space
  230. * @dev: Our DRM device
  231. * @len: length (bytes) of address space required
  232. * @name: resource name
  233. * @backed: resource should be backed by stolen pages
  234. *
  235. * Ask the kernel core to find us a suitable range of addresses
  236. * to use for a GTT mapping.
  237. *
  238. * Returns a gtt_range structure describing the object, or NULL on
  239. * error. On successful return the resource is both allocated and marked
  240. * as in use.
  241. */
  242. struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
  243. const char *name, int backed)
  244. {
  245. struct drm_psb_private *dev_priv = dev->dev_private;
  246. struct gtt_range *gt;
  247. struct resource *r = dev_priv->gtt_mem;
  248. int ret;
  249. unsigned long start, end;
  250. if (backed) {
  251. /* The start of the GTT is the stolen pages */
  252. start = r->start;
  253. end = r->start + dev_priv->gtt.stolen_size - 1;
  254. } else {
  255. /* The rest we will use for GEM backed objects */
  256. start = r->start + dev_priv->gtt.stolen_size;
  257. end = r->end;
  258. }
  259. gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL);
  260. if (gt == NULL)
  261. return NULL;
  262. gt->resource.name = name;
  263. gt->stolen = backed;
  264. gt->in_gart = backed;
  265. /* Ensure this is set for non GEM objects */
  266. gt->gem.dev = dev;
  267. ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
  268. len, start, end, PAGE_SIZE, NULL, NULL);
  269. if (ret == 0) {
  270. gt->offset = gt->resource.start - r->start;
  271. return gt;
  272. }
  273. kfree(gt);
  274. return NULL;
  275. }
  276. /**
  277. * psb_gtt_free_range - release GTT address space
  278. * @dev: our DRM device
  279. * @gt: a mapping created with psb_gtt_alloc_range
  280. *
  281. * Release a resource that was allocated with psb_gtt_alloc_range. If the
  282. * object has been pinned by mmap users we clean this up here currently.
  283. */
  284. void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
  285. {
  286. /* Undo the mmap pin if we are destroying the object */
  287. if (gt->mmapping) {
  288. psb_gtt_unpin(gt);
  289. gt->mmapping = 0;
  290. }
  291. WARN_ON(gt->in_gart && !gt->stolen);
  292. release_resource(&gt->resource);
  293. kfree(gt);
  294. }
  295. void psb_gtt_alloc(struct drm_device *dev)
  296. {
  297. struct drm_psb_private *dev_priv = dev->dev_private;
  298. init_rwsem(&dev_priv->gtt.sem);
  299. }
  300. void psb_gtt_takedown(struct drm_device *dev)
  301. {
  302. struct drm_psb_private *dev_priv = dev->dev_private;
  303. if (dev_priv->gtt_map) {
  304. iounmap(dev_priv->gtt_map);
  305. dev_priv->gtt_map = NULL;
  306. }
  307. if (dev_priv->gtt_initialized) {
  308. pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
  309. dev_priv->gmch_ctrl);
  310. PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL);
  311. (void) PSB_RVDC32(PSB_PGETBL_CTL);
  312. }
  313. if (dev_priv->vram_addr)
  314. iounmap(dev_priv->gtt_map);
  315. }
  316. int psb_gtt_init(struct drm_device *dev, int resume)
  317. {
  318. struct drm_psb_private *dev_priv = dev->dev_private;
  319. unsigned gtt_pages;
  320. unsigned long stolen_size, vram_stolen_size;
  321. unsigned i, num_pages;
  322. unsigned pfn_base;
  323. uint32_t vram_pages;
  324. uint32_t dvmt_mode = 0;
  325. struct psb_gtt *pg;
  326. int ret = 0;
  327. uint32_t pte;
  328. mutex_init(&dev_priv->gtt_mutex);
  329. psb_gtt_alloc(dev);
  330. pg = &dev_priv->gtt;
  331. /* Enable the GTT */
  332. pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl);
  333. pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
  334. dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
  335. dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
  336. PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
  337. (void) PSB_RVDC32(PSB_PGETBL_CTL);
  338. /* The root resource we allocate address space from */
  339. dev_priv->gtt_initialized = 1;
  340. pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
  341. /*
  342. * FIXME: video mmu has hw bug to access 0x0D0000000,
  343. * then make gatt start at 0x0e000,0000
  344. */
  345. pg->mmu_gatt_start = 0xE0000000;
  346. pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
  347. gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE)
  348. >> PAGE_SHIFT;
  349. /* CDV workaround */
  350. if (pg->gtt_start == 0 || gtt_pages == 0) {
  351. dev_err(dev->dev, "GTT PCI BAR not initialized.\n");
  352. gtt_pages = 64;
  353. pg->gtt_start = dev_priv->pge_ctl;
  354. }
  355. pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
  356. pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
  357. >> PAGE_SHIFT;
  358. dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
  359. if (pg->gatt_pages == 0 || pg->gatt_start == 0) {
  360. static struct resource fudge; /* Preferably peppermint */
  361. /* This can occur on CDV SDV systems. Fudge it in this case.
  362. We really don't care what imaginary space is being allocated
  363. at this point */
  364. dev_err(dev->dev, "GATT PCI BAR not initialized.\n");
  365. pg->gatt_start = 0x40000000;
  366. pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT;
  367. fudge.start = 0x40000000;
  368. fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1;
  369. fudge.name = "fudge";
  370. fudge.flags = IORESOURCE_MEM;
  371. dev_priv->gtt_mem = &fudge;
  372. }
  373. pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base);
  374. vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base
  375. - PAGE_SIZE;
  376. stolen_size = vram_stolen_size;
  377. printk(KERN_INFO "Stolen memory information\n");
  378. printk(KERN_INFO " base in RAM: 0x%x\n", dev_priv->stolen_base);
  379. printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
  380. vram_stolen_size/1024);
  381. dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7;
  382. printk(KERN_INFO " the correct size should be: %dM(dvmt mode=%d)\n",
  383. (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
  384. if (resume && (gtt_pages != pg->gtt_pages) &&
  385. (stolen_size != pg->stolen_size)) {
  386. dev_err(dev->dev, "GTT resume error.\n");
  387. ret = -EINVAL;
  388. goto out_err;
  389. }
  390. pg->gtt_pages = gtt_pages;
  391. pg->stolen_size = stolen_size;
  392. dev_priv->vram_stolen_size = vram_stolen_size;
  393. /*
  394. * Map the GTT and the stolen memory area
  395. */
  396. dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start,
  397. gtt_pages << PAGE_SHIFT);
  398. if (!dev_priv->gtt_map) {
  399. dev_err(dev->dev, "Failure to map gtt.\n");
  400. ret = -ENOMEM;
  401. goto out_err;
  402. }
  403. dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
  404. if (!dev_priv->vram_addr) {
  405. dev_err(dev->dev, "Failure to map stolen base.\n");
  406. ret = -ENOMEM;
  407. goto out_err;
  408. }
  409. /*
  410. * Insert vram stolen pages into the GTT
  411. */
  412. pfn_base = dev_priv->stolen_base >> PAGE_SHIFT;
  413. vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
  414. printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
  415. num_pages, pfn_base << PAGE_SHIFT, 0);
  416. for (i = 0; i < num_pages; ++i) {
  417. pte = psb_gtt_mask_pte(pfn_base + i, 0);
  418. iowrite32(pte, dev_priv->gtt_map + i);
  419. }
  420. /*
  421. * Init rest of GTT to the scratch page to avoid accidents or scribbles
  422. */
  423. pfn_base = page_to_pfn(dev_priv->scratch_page);
  424. pte = psb_gtt_mask_pte(pfn_base, 0);
  425. for (; i < gtt_pages; ++i)
  426. iowrite32(pte, dev_priv->gtt_map + i);
  427. (void) ioread32(dev_priv->gtt_map + i - 1);
  428. return 0;
  429. out_err:
  430. psb_gtt_takedown(dev);
  431. return ret;
  432. }