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

Commit f8f235e5 authored by Zhenyu Wang's avatar Zhenyu Wang Committed by Chris Wilson
Browse files

agp/intel: Fix cache control for Sandybridge



Sandybridge GTT has new cache control bits in PTE, which controls
graphics page cache in LLC or LLC/MLC, so we need to extend the mask
function to respect the new bits.

And set cache control to always LLC only by default on Gen6.

Signed-off-by: default avatarZhenyu Wang <zhenyuw@linux.intel.com>
Cc: stable@kernel.org
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 93f5f7f1
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -12,6 +12,7 @@
#include <asm/smp.h>
#include <asm/smp.h>
#include "agp.h"
#include "agp.h"
#include "intel-agp.h"
#include "intel-agp.h"
#include <linux/intel-gtt.h>


#include "intel-gtt.c"
#include "intel-gtt.c"


+40 −10
Original line number Original line Diff line number Diff line
@@ -49,6 +49,26 @@ static struct gatt_mask intel_i810_masks[] =
	 .type = INTEL_AGP_CACHED_MEMORY}
	 .type = INTEL_AGP_CACHED_MEMORY}
};
};


#define INTEL_AGP_UNCACHED_MEMORY              0
#define INTEL_AGP_CACHED_MEMORY_LLC            1
#define INTEL_AGP_CACHED_MEMORY_LLC_GFDT       2
#define INTEL_AGP_CACHED_MEMORY_LLC_MLC        3
#define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT   4

static struct gatt_mask intel_gen6_masks[] =
{
	{.mask = I810_PTE_VALID | GEN6_PTE_UNCACHED,
	 .type = INTEL_AGP_UNCACHED_MEMORY },
	{.mask = I810_PTE_VALID | GEN6_PTE_LLC,
         .type = INTEL_AGP_CACHED_MEMORY_LLC },
	{.mask = I810_PTE_VALID | GEN6_PTE_LLC | GEN6_PTE_GFDT,
         .type = INTEL_AGP_CACHED_MEMORY_LLC_GFDT },
	{.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC,
         .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC },
	{.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC | GEN6_PTE_GFDT,
         .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT },
};

static struct _intel_private {
static struct _intel_private {
	struct pci_dev *pcidev;	/* device one */
	struct pci_dev *pcidev;	/* device one */
	u8 __iomem *registers;
	u8 __iomem *registers;
@@ -178,13 +198,6 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem,
					off_t pg_start, int mask_type)
					off_t pg_start, int mask_type)
{
{
	int i, j;
	int i, j;
	u32 cache_bits = 0;

	if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
	    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
	{
		cache_bits = GEN6_PTE_LLC_MLC;
	}


	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
		writel(agp_bridge->driver->mask_memory(agp_bridge,
		writel(agp_bridge->driver->mask_memory(agp_bridge,
@@ -317,6 +330,23 @@ static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
		return 0;
		return 0;
}
}


static int intel_gen6_type_to_mask_type(struct agp_bridge_data *bridge,
					int type)
{
	unsigned int type_mask = type & ~AGP_USER_CACHED_MEMORY_GFDT;
	unsigned int gfdt = type & AGP_USER_CACHED_MEMORY_GFDT;

	if (type_mask == AGP_USER_UNCACHED_MEMORY)
		return INTEL_AGP_UNCACHED_MEMORY;
	else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC)
		return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT :
			      INTEL_AGP_CACHED_MEMORY_LLC_MLC;
	else /* set 'normal'/'cached' to LLC by default */
		return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_GFDT :
			      INTEL_AGP_CACHED_MEMORY_LLC;
}


static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
				int type)
				int type)
{
{
@@ -1163,7 +1193,7 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start,


	mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
	mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);


	if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
	if (!IS_SNB && mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
	    mask_type != INTEL_AGP_CACHED_MEMORY)
	    mask_type != INTEL_AGP_CACHED_MEMORY)
		goto out_err;
		goto out_err;


@@ -1563,7 +1593,7 @@ static const struct agp_bridge_driver intel_gen6_driver = {
	.fetch_size		= intel_i9xx_fetch_size,
	.fetch_size		= intel_i9xx_fetch_size,
	.cleanup		= intel_i915_cleanup,
	.cleanup		= intel_i915_cleanup,
	.mask_memory		= intel_gen6_mask_memory,
	.mask_memory		= intel_gen6_mask_memory,
	.masks			= intel_i810_masks,
	.masks			= intel_gen6_masks,
	.agp_enable		= intel_i810_agp_enable,
	.agp_enable		= intel_i810_agp_enable,
	.cache_flush		= global_cache_flush,
	.cache_flush		= global_cache_flush,
	.create_gatt_table	= intel_i965_create_gatt_table,
	.create_gatt_table	= intel_i965_create_gatt_table,
@@ -1576,7 +1606,7 @@ static const struct agp_bridge_driver intel_gen6_driver = {
	.agp_alloc_pages        = agp_generic_alloc_pages,
	.agp_alloc_pages        = agp_generic_alloc_pages,
	.agp_destroy_page	= agp_generic_destroy_page,
	.agp_destroy_page	= agp_generic_destroy_page,
	.agp_destroy_pages      = agp_generic_destroy_pages,
	.agp_destroy_pages      = agp_generic_destroy_pages,
	.agp_type_to_mask_type	= intel_i830_type_to_mask_type,
	.agp_type_to_mask_type	= intel_gen6_type_to_mask_type,
	.chipset_flush		= intel_i915_chipset_flush,
	.chipset_flush		= intel_i915_chipset_flush,
#ifdef USE_PCI_DMA_API
#ifdef USE_PCI_DMA_API
	.agp_map_page		= intel_agp_map_page,
	.agp_map_page		= intel_agp_map_page,
+1 −0
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/swap.h>
#include <linux/swap.h>
#include <linux/pci.h>
#include <linux/pci.h>
#include <linux/intel-gtt.h>


static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj);
static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj);
static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
+20 −0
Original line number Original line Diff line number Diff line
/*
 * Common Intel AGPGART and GTT definitions.
 */
#ifndef _INTEL_GTT_H
#define _INTEL_GTT_H

#include <linux/agp_backend.h>

/* This is for Intel only GTT controls.
 *
 * Sandybridge: AGP_USER_CACHED_MEMORY default to LLC only
 */

#define AGP_USER_CACHED_MEMORY_LLC_MLC (AGP_USER_TYPES + 2)
#define AGP_USER_UNCACHED_MEMORY (AGP_USER_TYPES + 4)

/* flag for GFDT type */
#define AGP_USER_CACHED_MEMORY_GFDT (1 << 3)

#endif