drm/gma500: Hook up the MMU
authorPatrik Jakobsson <patrik.r.jakobsson@gmail.com>
Sat, 4 Jan 2014 21:11:17 +0000 (22:11 +0100)
committerPatrik Jakobsson <patrik.r.jakobsson@gmail.com>
Mon, 17 Mar 2014 19:11:53 +0000 (20:11 +0100)
Properly init the MMU and add MMU entries when adding GTT entries

Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
drivers/gpu/drm/gma500/gtt.c
drivers/gpu/drm/gma500/psb_drv.c

index 2db731f..a30f6ee 100644 (file)
@@ -22,6 +22,7 @@
 #include <drm/drmP.h>
 #include <linux/shmem_fs.h>
 #include "psb_drv.h"
+#include "blitter.h"
 
 
 /*
@@ -105,11 +106,13 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r,
 
        /* Write our page entries into the GTT itself */
        for (i = r->roll; i < r->npage; i++) {
-               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
+                                      PSB_MMU_CACHED_MEMORY);
                iowrite32(pte, gtt_slot++);
        }
        for (i = 0; i < r->roll; i++) {
-               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
+                                      PSB_MMU_CACHED_MEMORY);
                iowrite32(pte, gtt_slot++);
        }
        /* Make sure all the entries are set before we return */
@@ -127,7 +130,7 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r,
  *     page table entries with the dummy page. This is protected via the gtt
  *     mutex which the caller must hold.
  */
-static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
+void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
        u32 __iomem *gtt_slot;
@@ -137,7 +140,8 @@ static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
        WARN_ON(r->stolen);
 
        gtt_slot = psb_gtt_entry(dev, r);
-       pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);
+       pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page),
+                              PSB_MMU_CACHED_MEMORY);
 
        for (i = 0; i < r->npage; i++)
                iowrite32(pte, gtt_slot++);
@@ -176,11 +180,13 @@ void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll)
        gtt_slot = psb_gtt_entry(dev, r);
 
        for (i = r->roll; i < r->npage; i++) {
-               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
+                                      PSB_MMU_CACHED_MEMORY);
                iowrite32(pte, gtt_slot++);
        }
        for (i = 0; i < r->roll; i++) {
-               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+               pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
+                                      PSB_MMU_CACHED_MEMORY);
                iowrite32(pte, gtt_slot++);
        }
        ioread32(gtt_slot - 1);
@@ -240,6 +246,7 @@ int psb_gtt_pin(struct gtt_range *gt)
        int ret = 0;
        struct drm_device *dev = gt->gem.dev;
        struct drm_psb_private *dev_priv = dev->dev_private;
+       u32 gpu_base = dev_priv->gtt.gatt_start;
 
        mutex_lock(&dev_priv->gtt_mutex);
 
@@ -252,6 +259,9 @@ int psb_gtt_pin(struct gtt_range *gt)
                        psb_gtt_detach_pages(gt);
                        goto out;
                }
+               psb_mmu_insert_pages(psb_mmu_get_default_pd(dev_priv->mmu),
+                                    gt->pages, (gpu_base + gt->offset),
+                                    gt->npage, 0, 0, PSB_MMU_CACHED_MEMORY);
        }
        gt->in_gart++;
 out:
@@ -274,16 +284,30 @@ void psb_gtt_unpin(struct gtt_range *gt)
 {
        struct drm_device *dev = gt->gem.dev;
        struct drm_psb_private *dev_priv = dev->dev_private;
+       u32 gpu_base = dev_priv->gtt.gatt_start;
+       int ret;
 
+       /* While holding the gtt_mutex no new blits can be initiated */
        mutex_lock(&dev_priv->gtt_mutex);
 
+       /* Wait for any possible usage of the memory to be finished */
+       ret = gma_blt_wait_idle(dev_priv);
+       if (ret) {
+               DRM_ERROR("Failed to idle the blitter, unpin failed!");
+               goto out;
+       }
+
        WARN_ON(!gt->in_gart);
 
        gt->in_gart--;
        if (gt->in_gart == 0 && gt->stolen == 0) {
+               psb_mmu_remove_pages(psb_mmu_get_default_pd(dev_priv->mmu),
+                                    (gpu_base + gt->offset), gt->npage, 0, 0);
                psb_gtt_remove(dev, gt);
                psb_gtt_detach_pages(gt);
        }
+
+out:
        mutex_unlock(&dev_priv->gtt_mutex);
 }
 
@@ -497,6 +521,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
        if (!resume)
                dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base,
                                                 stolen_size);
+
        if (!dev_priv->vram_addr) {
                dev_err(dev->dev, "Failure to map stolen base.\n");
                ret = -ENOMEM;
@@ -512,7 +537,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
        dev_dbg(dev->dev, "Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
                num_pages, pfn_base << PAGE_SHIFT, 0);
        for (i = 0; i < num_pages; ++i) {
-               pte = psb_gtt_mask_pte(pfn_base + i, 0);
+               pte = psb_gtt_mask_pte(pfn_base + i, PSB_MMU_CACHED_MEMORY);
                iowrite32(pte, dev_priv->gtt_map + i);
        }
 
@@ -521,7 +546,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
         */
 
        pfn_base = page_to_pfn(dev_priv->scratch_page);
-       pte = psb_gtt_mask_pte(pfn_base, 0);
+       pte = psb_gtt_mask_pte(pfn_base, PSB_MMU_CACHED_MEMORY);
        for (; i < gtt_pages; ++i)
                iowrite32(pte, dev_priv->gtt_map + i);
 
index 55eef4d..89804fd 100644 (file)
@@ -192,12 +192,18 @@ static int psb_do_init(struct drm_device *dev)
        PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
        PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
        PSB_RSGX32(PSB_CR_BIF_BANK1);
-       PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK,
-                                                       PSB_CR_BIF_CTRL);
+
+       /* Do not bypass any MMU access, let them pagefault instead */
+       PSB_WSGX32((PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_MMU_ER_MASK),
+                  PSB_CR_BIF_CTRL);
+       PSB_RSGX32(PSB_CR_BIF_CTRL);
+
        psb_spank(dev_priv);
 
        /* mmu_gatt ?? */
        PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
+       PSB_RSGX32(PSB_CR_BIF_TWOD_REQ_BASE); /* Post */
+
        return 0;
 out_err:
        return ret;
@@ -277,6 +283,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
        int ret = -ENOMEM;
        struct drm_connector *connector;
        struct gma_encoder *gma_encoder;
+       struct psb_gtt *pg;
 
        dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
        if (dev_priv == NULL)
@@ -286,6 +293,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
        dev_priv->dev = dev;
        dev->dev_private = (void *) dev_priv;
 
+       pg = &dev_priv->gtt;
+
        pci_set_master(dev->pdev);
 
        dev_priv->num_pipe = dev_priv->ops->pipes;
@@ -355,13 +364,21 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
        if (!dev_priv->pf_pd)
                goto out_err;
 
-       psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
-       psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
-
        ret = psb_do_init(dev);
        if (ret)
                return ret;
 
+       /* Add stolen memory to SGX MMU */
+       down_read(&pg->sem);
+       ret = psb_mmu_insert_pfn_sequence(psb_mmu_get_default_pd(dev_priv->mmu),
+                                         dev_priv->stolen_base >> PAGE_SHIFT,
+                                         pg->gatt_start,
+                                         pg->stolen_size >> PAGE_SHIFT, 0);
+       up_read(&pg->sem);
+
+       psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
+       psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
+
        PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE);
        PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE);