Skip to content

Commit

Permalink
agp/intel: Fix cache control for Sandybridge
Browse files Browse the repository at this point in the history
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: Zhenyu Wang <zhenyuw@linux.intel.com>
Cc: stable@kernel.org
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
  • Loading branch information
Zhenyu Wang authored and Chris Wilson committed Sep 7, 2010
1 parent 93f5f7f commit f8f235e
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 10 deletions.
1 change: 1 addition & 0 deletions drivers/char/agp/intel-agp.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <asm/smp.h>
#include "agp.h"
#include "intel-agp.h"
#include <linux/intel-gtt.h>

#include "intel-gtt.c"

Expand Down
50 changes: 40 additions & 10 deletions drivers/char/agp/intel-gtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,26 @@ static struct gatt_mask intel_i810_masks[] =
.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 {
struct pci_dev *pcidev; /* device one */
u8 __iomem *registers;
Expand Down Expand Up @@ -178,13 +198,6 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem,
off_t pg_start, int mask_type)
{
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++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
Expand Down Expand Up @@ -317,6 +330,23 @@ static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
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,
int type)
{
Expand Down Expand Up @@ -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);

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)
goto out_err;

Expand Down Expand Up @@ -1563,7 +1593,7 @@ static const struct agp_bridge_driver intel_gen6_driver = {
.fetch_size = intel_i9xx_fetch_size,
.cleanup = intel_i915_cleanup,
.mask_memory = intel_gen6_mask_memory,
.masks = intel_i810_masks,
.masks = intel_gen6_masks,
.agp_enable = intel_i810_agp_enable,
.cache_flush = global_cache_flush,
.create_gatt_table = intel_i965_create_gatt_table,
Expand All @@ -1576,7 +1606,7 @@ static const struct agp_bridge_driver intel_gen6_driver = {
.agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
.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,
#ifdef USE_PCI_DMA_API
.agp_map_page = intel_agp_map_page,
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <linux/slab.h>
#include <linux/swap.h>
#include <linux/pci.h>
#include <linux/intel-gtt.h>

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);
Expand Down
20 changes: 20 additions & 0 deletions include/linux/intel-gtt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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

0 comments on commit f8f235e

Please sign in to comment.