* devices this will probably be ignored */
 };
 
+#define AGP_PAGE_DESTROY_UNMAP 1
+#define AGP_PAGE_DESTROY_FREE 2
+
 struct aper_size_info_8 {
        int size;
        int num_entries;
        struct agp_memory *(*alloc_by_type) (size_t, int);
        void (*free_by_type)(struct agp_memory *);
        void *(*agp_alloc_page)(struct agp_bridge_data *);
-       void (*agp_destroy_page)(void *);
+       void (*agp_destroy_page)(void *, int flags);
         int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
 };
 
 struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type);
 void agp_generic_free_by_type(struct agp_memory *curr);
 void *agp_generic_alloc_page(struct agp_bridge_data *bridge);
-void agp_generic_destroy_page(void *addr);
+void agp_generic_destroy_page(void *addr, int flags);
 void agp_free_key(int key);
 int agp_num_entries(void);
 u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 mode, u32 command);
 
        return addr;
 }
 
-static void ali_destroy_page(void * addr)
+static void ali_destroy_page(void * addr, int flags)
 {
        if (addr) {
-               global_cache_flush();   /* is this really needed?  --hch */
-               agp_generic_destroy_page(addr);
-               global_flush_tlb();
+               if (flags & AGP_PAGE_DESTROY_UNMAP) {
+                       global_cache_flush();   /* is this really needed?  --hch */
+                       agp_generic_destroy_page(addr, flags);
+                       global_flush_tlb();
+               } else
+                       agp_generic_destroy_page(addr, flags);
        }
 }
 
-static void m1541_destroy_page(void * addr)
+static void m1541_destroy_page(void * addr, int flags)
 {
        u32 temp;
 
        if (addr == NULL)
                return;
 
-       global_cache_flush();
+       if (flags & AGP_PAGE_DESTROY_UNMAP) {
+               global_cache_flush();
 
-       pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
-       pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
-                       (((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
-                         virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN));
-       agp_generic_destroy_page(addr);
+               pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
+               pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
+                                      (((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
+                                        virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN));
+       }
+       agp_generic_destroy_page(addr, flags);
 }
 
 
 
 
 err_out:
        if (bridge->driver->needs_scratch_page) {
-               bridge->driver->agp_destroy_page(
-                               gart_to_virt(bridge->scratch_page_real));
+               bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
+                                                AGP_PAGE_DESTROY_UNMAP);
                flush_agp_mappings();
+               bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
+                                                AGP_PAGE_DESTROY_FREE);
        }
        if (got_gatt)
                bridge->driver->free_gatt_table(bridge);
 
        if (bridge->driver->agp_destroy_page &&
            bridge->driver->needs_scratch_page) {
-               bridge->driver->agp_destroy_page(
-                               gart_to_virt(bridge->scratch_page_real));
+               bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
+                                                AGP_PAGE_DESTROY_UNMAP);
                flush_agp_mappings();
+               bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
+                                                AGP_PAGE_DESTROY_FREE);
        }
 }
 
 
        }
        if (curr->page_count != 0) {
                for (i = 0; i < curr->page_count; i++) {
-                       curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]));
+                       curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]), AGP_PAGE_DESTROY_UNMAP);
                }
                flush_agp_mappings();
+               for (i = 0; i < curr->page_count; i++) {
+                       curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]), AGP_PAGE_DESTROY_FREE);
+               }
        }
        agp_free_key(curr->key);
        agp_free_page_array(curr);
 EXPORT_SYMBOL(agp_generic_alloc_page);
 
 
-void agp_generic_destroy_page(void *addr)
+void agp_generic_destroy_page(void *addr, int flags)
 {
        struct page *page;
 
                return;
 
        page = virt_to_page(addr);
-       unmap_page_from_agp(page);
-       put_page(page);
-       free_page((unsigned long)addr);
-       atomic_dec(&agp_bridge->current_memory_agp);
+       if (flags & AGP_PAGE_DESTROY_UNMAP)
+               unmap_page_from_agp(page);
+
+       if (flags & AGP_PAGE_DESTROY_FREE) {
+               put_page(page);
+               free_page((unsigned long)addr);
+               atomic_dec(&agp_bridge->current_memory_agp);
+       }
 }
 EXPORT_SYMBOL(agp_generic_destroy_page);
 
 
        return page;
 }
 
-static void i460_destroy_page (void *page)
+static void i460_destroy_page (void *page, int flags)
 {
        if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) {
-               agp_generic_destroy_page(page);
+               agp_generic_destroy_page(page, flags);
                global_flush_tlb();
        }
 }
 
                if (curr->page_count == 4)
                        i8xx_destroy_pages(gart_to_virt(curr->memory[0]));
                else {
-                       agp_bridge->driver->agp_destroy_page(
-                                gart_to_virt(curr->memory[0]));
+                       agp_bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[0]),
+                                                            AGP_PAGE_DESTROY_UNMAP);
                        global_flush_tlb();
+                       agp_bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[0]),
+                                                            AGP_PAGE_DESTROY_FREE);
                }
                agp_free_page_array(curr);
        }