Convert most AGP chipset to use scratch page as default entries.
This help avoiding GPU querying 0 address and trigger computer
fault. With KMS and memory manager we bind/unbind AGP memory
constantly and it seems that some GPU are still doing AGP
traffic even after GPU report being idle with the memory segment.

Tested (radeon GPU KMS + Xorg + compiz + glxgears + quake3) on :
- SIS 1039:0001 & 1039:0003
- Intel 865 8086:2571

Compile tested for other bridges

V2 enable scratch page on uninorth
V3 fix unbound check in uninorth insert memory (Michel D?nzer)
V4 rebase on top of drm-next branch with the lastest intel AGP
   changeset (stable should use version V3 of the patch)

Signed-off-by: Jerome Glisse <jglisse at redhat.com>
Signed-off-by: Michel D?nzer <michel at daenzer.net>
Cc: stable <stable at kernel.org>
---
 drivers/char/agp/ali-agp.c      |    1 +
 drivers/char/agp/amd-k7-agp.c   |    9 +++++++++
 drivers/char/agp/amd64-agp.c    |    1 +
 drivers/char/agp/ati-agp.c      |    8 ++++++++
 drivers/char/agp/intel-agp.c    |    9 +++++++++
 drivers/char/agp/nvidia-agp.c   |    1 +
 drivers/char/agp/sis-agp.c      |    1 +
 drivers/char/agp/uninorth-agp.c |   16 ++++++++++++----
 drivers/char/agp/via-agp.c      |    2 ++
 9 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index d2ce68f..fd79351 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -204,6 +204,7 @@ static const struct agp_bridge_driver ali_generic_bridge = {
        .aperture_sizes         = ali_generic_sizes,
        .size_type              = U32_APER_SIZE,
        .num_aperture_sizes     = 7,
+       .needs_scratch_page     = true,
        .configure              = ali_configure,
        .fetch_size             = ali_fetch_size,
        .cleanup                = ali_cleanup,
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index a7637d7..b6b1568 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -142,6 +142,7 @@ static int amd_create_gatt_table(struct agp_bridge_data 
*bridge)
 {
        struct aper_size_info_lvl2 *value;
        struct amd_page_map page_dir;
+       unsigned long __iomem *cur_gatt;
        unsigned long addr;
        int retval;
        u32 temp;
@@ -178,6 +179,13 @@ static int amd_create_gatt_table(struct agp_bridge_data 
*bridge)
                readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr));        /* PCI 
Posting. */
        }

+       for (i = 0; i < value->num_entries; i++) {
+               addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
+               cur_gatt = GET_GATT(addr);
+               writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
+               readl(cur_gatt+GET_GATT_OFF(addr));     /* PCI Posting. */
+       }
+
        return 0;
 }

@@ -375,6 +383,7 @@ static const struct agp_bridge_driver amd_irongate_driver = 
{
        .aperture_sizes         = amd_irongate_sizes,
        .size_type              = LVL2_APER_SIZE,
        .num_aperture_sizes     = 7,
+       .needs_scratch_page     = true,
        .configure              = amd_irongate_configure,
        .fetch_size             = amd_irongate_fetch_size,
        .cleanup                = amd_irongate_cleanup,
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index fd50ead..73703b1 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -210,6 +210,7 @@ static const struct agp_bridge_driver amd_8151_driver = {
        .aperture_sizes         = amd_8151_sizes,
        .size_type              = U32_APER_SIZE,
        .num_aperture_sizes     = 7,
+       .needs_scratch_page     = true,
        .configure              = amd_8151_configure,
        .fetch_size             = amd64_fetch_size,
        .cleanup                = amd64_cleanup,
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index 3b2ecbe..dc30e22 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -341,6 +341,7 @@ static int ati_create_gatt_table(struct agp_bridge_data 
*bridge)
 {
        struct aper_size_info_lvl2 *value;
        struct ati_page_map page_dir;
+       unsigned long __iomem *cur_gatt;
        unsigned long addr;
        int retval;
        u32 temp;
@@ -395,6 +396,12 @@ static int ati_create_gatt_table(struct agp_bridge_data 
*bridge)
                readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr));        /* PCI 
Posting. */
        }

+       for (i = 0; i < value->num_entries; i++) {
+               addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
+               cur_gatt = GET_GATT(addr);
+               writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
+       }
+
        return 0;
 }

@@ -415,6 +422,7 @@ static const struct agp_bridge_driver ati_generic_bridge = {
        .aperture_sizes         = ati_generic_sizes,
        .size_type              = LVL2_APER_SIZE,
        .num_aperture_sizes     = 7,
+       .needs_scratch_page     = true,
        .configure              = ati_configure,
        .fetch_size             = ati_fetch_size,
        .cleanup                = ati_cleanup,
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 034644e..d836a71 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -464,6 +464,7 @@ static const struct agp_bridge_driver intel_generic_driver 
= {
        .aperture_sizes         = intel_generic_sizes,
        .size_type              = U16_APER_SIZE,
        .num_aperture_sizes     = 7,
+       .needs_scratch_page     = true,
        .configure              = intel_configure,
        .fetch_size             = intel_fetch_size,
        .cleanup                = intel_cleanup,
@@ -490,6 +491,7 @@ static const struct agp_bridge_driver intel_815_driver = {
        .aperture_sizes         = intel_815_sizes,
        .size_type              = U8_APER_SIZE,
        .num_aperture_sizes     = 2,
+       .needs_scratch_page     = true,
        .configure              = intel_815_configure,
        .fetch_size             = intel_815_fetch_size,
        .cleanup                = intel_8xx_cleanup,
@@ -516,6 +518,7 @@ static const struct agp_bridge_driver intel_820_driver = {
        .aperture_sizes         = intel_8xx_sizes,
        .size_type              = U8_APER_SIZE,
        .num_aperture_sizes     = 7,
+       .needs_scratch_page     = true,
        .configure              = intel_820_configure,
        .fetch_size             = intel_8xx_fetch_size,
        .cleanup                = intel_820_cleanup,
@@ -542,6 +545,7 @@ static const struct agp_bridge_driver intel_830mp_driver = {
        .aperture_sizes         = intel_830mp_sizes,
        .size_type              = U8_APER_SIZE,
        .num_aperture_sizes     = 4,
+       .needs_scratch_page     = true,
        .configure              = intel_830mp_configure,
        .fetch_size             = intel_8xx_fetch_size,
        .cleanup                = intel_8xx_cleanup,
@@ -568,6 +572,7 @@ static const struct agp_bridge_driver intel_840_driver = {
        .aperture_sizes         = intel_8xx_sizes,
        .size_type              = U8_APER_SIZE,
        .num_aperture_sizes     = 7,
+       .needs_scratch_page     = true,
        .configure              = intel_840_configure,
        .fetch_size             = intel_8xx_fetch_size,
        .cleanup                = intel_8xx_cleanup,
@@ -594,6 +599,7 @@ static const struct agp_bridge_driver intel_845_driver = {
        .aperture_sizes         = intel_8xx_sizes,
        .size_type              = U8_APER_SIZE,
        .num_aperture_sizes     = 7,
+       .needs_scratch_page     = true,
        .configure              = intel_845_configure,
        .fetch_size             = intel_8xx_fetch_size,
        .cleanup                = intel_8xx_cleanup,
@@ -620,6 +626,7 @@ static const struct agp_bridge_driver intel_850_driver = {
        .aperture_sizes         = intel_8xx_sizes,
        .size_type              = U8_APER_SIZE,
        .num_aperture_sizes     = 7,
+       .needs_scratch_page     = true,
        .configure              = intel_850_configure,
        .fetch_size             = intel_8xx_fetch_size,
        .cleanup                = intel_8xx_cleanup,
@@ -646,6 +653,7 @@ static const struct agp_bridge_driver intel_860_driver = {
        .aperture_sizes         = intel_8xx_sizes,
        .size_type              = U8_APER_SIZE,
        .num_aperture_sizes     = 7,
+       .needs_scratch_page     = true,
        .configure              = intel_860_configure,
        .fetch_size             = intel_8xx_fetch_size,
        .cleanup                = intel_8xx_cleanup,
@@ -672,6 +680,7 @@ static const struct agp_bridge_driver intel_7505_driver = {
        .aperture_sizes         = intel_8xx_sizes,
        .size_type              = U8_APER_SIZE,
        .num_aperture_sizes     = 7,
+       .needs_scratch_page     = true,
        .configure              = intel_7505_configure,
        .fetch_size             = intel_8xx_fetch_size,
        .cleanup                = intel_8xx_cleanup,
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index 10f24e3..b9734a9 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -310,6 +310,7 @@ static const struct agp_bridge_driver nvidia_driver = {
        .aperture_sizes         = nvidia_generic_sizes,
        .size_type              = U8_APER_SIZE,
        .num_aperture_sizes     = 5,
+       .needs_scratch_page     = true,
        .configure              = nvidia_configure,
        .fetch_size             = nvidia_fetch_size,
        .cleanup                = nvidia_cleanup,
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index 6c3837a..b53d5f4 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -125,6 +125,7 @@ static struct agp_bridge_driver sis_driver = {
        .aperture_sizes         = sis_generic_sizes,
        .size_type              = U8_APER_SIZE,
        .num_aperture_sizes     = 7,
+       .needs_scratch_page     = true,
        .configure              = sis_configure,
        .fetch_size             = sis_fetch_size,
        .cleanup                = sis_cleanup,
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index 6f48931..95db713 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -28,6 +28,7 @@
  */
 static int uninorth_rev;
 static int is_u3;
+static u32 scratch_value;

 #define DEFAULT_APERTURE_SIZE 256
 #define DEFAULT_APERTURE_STRING "256"
@@ -172,7 +173,7 @@ static int uninorth_insert_memory(struct agp_memory *mem, 
off_t pg_start, int ty

        gp = (u32 *) &agp_bridge->gatt_table[pg_start];
        for (i = 0; i < mem->page_count; ++i) {
-               if (gp[i]) {
+               if (gp[i] != scratch_value) {
                        dev_info(&agp_bridge->dev->dev,
                                 "uninorth_insert_memory: entry 0x%x occupied 
(%x)\n",
                                 i, gp[i]);
@@ -214,8 +215,9 @@ int uninorth_remove_memory(struct agp_memory *mem, off_t 
pg_start, int type)
                return 0;

        gp = (u32 *) &agp_bridge->gatt_table[pg_start];
-       for (i = 0; i < mem->page_count; ++i)
-               gp[i] = 0;
+       for (i = 0; i < mem->page_count; ++i) {
+               gp[i] = scratch_value;
+       }
        mb();
        uninorth_tlbflush(mem);

@@ -421,8 +423,13 @@ static int uninorth_create_gatt_table(struct 
agp_bridge_data *bridge)

        bridge->gatt_bus_addr = virt_to_phys(table);

+       if (is_u3)
+               scratch_value = (page_to_phys(agp_bridge->scratch_page_page) >> 
PAGE_SHIFT) | 0x80000000UL;
+       else
+               scratch_value = 
cpu_to_le32((page_to_phys(agp_bridge->scratch_page_page) & 0xFFFFF000UL) |
+                               0x1UL);
        for (i = 0; i < num_entries; i++)
-               bridge->gatt_table[i] = 0;
+               bridge->gatt_table[i] = scratch_value;

        return 0;

@@ -519,6 +526,7 @@ const struct agp_bridge_driver uninorth_agp_driver = {
        .agp_destroy_pages      = agp_generic_destroy_pages,
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
        .cant_use_aperture      = true,
+       .needs_scratch_page     = true,
 };

 const struct agp_bridge_driver u3_agp_driver = {
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index d3bd243..df67e80 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -175,6 +175,7 @@ static const struct agp_bridge_driver via_agp3_driver = {
        .aperture_sizes         = agp3_generic_sizes,
        .size_type              = U8_APER_SIZE,
        .num_aperture_sizes     = 10,
+       .needs_scratch_page     = true,
        .configure              = via_configure_agp3,
        .fetch_size             = via_fetch_size_agp3,
        .cleanup                = via_cleanup_agp3,
@@ -201,6 +202,7 @@ static const struct agp_bridge_driver via_driver = {
        .aperture_sizes         = via_generic_sizes,
        .size_type              = U8_APER_SIZE,
        .num_aperture_sizes     = 9,
+       .needs_scratch_page     = true,
        .configure              = via_configure,
        .fetch_size             = via_fetch_size,
        .cleanup                = via_cleanup,
-- 
1.7.0.1

Reply via email to