Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae012bdc authored by Patrik Jakobsson's avatar Patrik Jakobsson
Browse files

drm/gma500: Hook up the MMU



Properly init the MMU and add MMU entries when adding GTT entries

Signed-off-by: default avatarPatrik Jakobsson <patrik.r.jakobsson@gmail.com>
parent 1c6b5d17
Loading
Loading
Loading
Loading
+33 −8
Original line number Diff line number Diff line
@@ -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);

+22 −5
Original line number Diff line number Diff line
@@ -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,

	/* 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);