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