include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / char / agp / uninorth-agp.c
index 37ff3bd..6f48931 100644 (file)
@@ -3,10 +3,12 @@
  */
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/pagemap.h>
 #include <linux/agp_backend.h>
 #include <linux/delay.h>
+#include <linux/vmalloc.h>
 #include <asm/uninorth.h>
 #include <asm/pci-bridge.h>
 #include <asm/prom.h>
@@ -137,22 +139,19 @@ static int uninorth_configure(void)
        if (is_u3) {
                pci_write_config_dword(agp_bridge->dev,
                                       UNI_N_CFG_GART_DUMMY_PAGE,
-                                      agp_bridge->scratch_page_real >> 12);
+                                      page_to_phys(agp_bridge->scratch_page_page) >> 12);
        }
 
        return 0;
 }
 
-static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start,
-                               int type)
+static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
-       int i, j, num_entries;
+       int i, num_entries;
        void *temp;
+       u32 *gp;
        int mask_type;
 
-       temp = agp_bridge->current_size;
-       num_entries = A_SIZE_32(temp)->num_entries;
-
        if (type != mem->type)
                return -EINVAL;
 
@@ -162,51 +161,12 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start,
                return -EINVAL;
        }
 
-       if ((pg_start + mem->page_count) > num_entries)
-               return -EINVAL;
-
-       j = pg_start;
-
-       while (j < (pg_start + mem->page_count)) {
-               if (agp_bridge->gatt_table[j])
-                       return -EBUSY;
-               j++;
-       }
-
-       for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-               agp_bridge->gatt_table[j] =
-                       cpu_to_le32((page_to_phys(mem->pages[i]) & 0xFFFFF000UL) | 0x1UL);
-               flush_dcache_range((unsigned long)__va(page_to_phys(mem->pages[i])),
-                                  (unsigned long)__va(page_to_phys(mem->pages[i]))+0x1000);
-       }
-       (void)in_le32((volatile u32*)&agp_bridge->gatt_table[pg_start]);
-       mb();
-       flush_dcache_range((unsigned long)&agp_bridge->gatt_table[pg_start],
-               (unsigned long)&agp_bridge->gatt_table[pg_start + mem->page_count]);
-
-       uninorth_tlbflush(mem);
-       return 0;
-}
-
-static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
-{
-       int i, num_entries;
-       void *temp;
-       u32 *gp;
-       int mask_type;
+       if (mem->page_count == 0)
+               return 0;
 
        temp = agp_bridge->current_size;
        num_entries = A_SIZE_32(temp)->num_entries;
 
-       if (type != mem->type)
-               return -EINVAL;
-
-       mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
-       if (mask_type != 0) {
-               /* We know nothing of memory types */
-               return -EINVAL;
-       }
-
        if ((pg_start + mem->page_count) > num_entries)
                return -EINVAL;
 
@@ -214,38 +174,49 @@ static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
        for (i = 0; i < mem->page_count; ++i) {
                if (gp[i]) {
                        dev_info(&agp_bridge->dev->dev,
-                                "u3_insert_memory: entry 0x%x occupied (%x)\n",
+                                "uninorth_insert_memory: entry 0x%x occupied (%x)\n",
                                 i, gp[i]);
                        return -EBUSY;
                }
        }
 
        for (i = 0; i < mem->page_count; i++) {
-               gp[i] = (page_to_phys(mem->pages[i]) >> PAGE_SHIFT) | 0x80000000UL;
+               if (is_u3)
+                       gp[i] = (page_to_phys(mem->pages[i]) >> PAGE_SHIFT) | 0x80000000UL;
+               else
+                       gp[i] = cpu_to_le32((page_to_phys(mem->pages[i]) & 0xFFFFF000UL) |
+                                           0x1UL);
                flush_dcache_range((unsigned long)__va(page_to_phys(mem->pages[i])),
                                   (unsigned long)__va(page_to_phys(mem->pages[i]))+0x1000);
        }
        mb();
-       flush_dcache_range((unsigned long)gp, (unsigned long) &gp[i]);
        uninorth_tlbflush(mem);
 
        return 0;
 }
 
-int u3_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
+int uninorth_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
        size_t i;
        u32 *gp;
+       int mask_type;
+
+       if (type != mem->type)
+               return -EINVAL;
 
-       if (type != 0 || mem->type != 0)
+       mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
+       if (mask_type != 0) {
                /* We know nothing of memory types */
                return -EINVAL;
+       }
+
+       if (mem->page_count == 0)
+               return 0;
 
        gp = (u32 *) &agp_bridge->gatt_table[pg_start];
        for (i = 0; i < mem->page_count; ++i)
                gp[i] = 0;
        mb();
-       flush_dcache_range((unsigned long)gp, (unsigned long) &gp[i]);
        uninorth_tlbflush(mem);
 
        return 0;
@@ -273,7 +244,7 @@ static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode)
 
        if ((uninorth_rev >= 0x30) && (uninorth_rev <= 0x33)) {
                /*
-                * We need to to set REQ_DEPTH to 7 for U3 versions 1.0, 2.1,
+                * We need to set REQ_DEPTH to 7 for U3 versions 1.0, 2.1,
                 * 2.2 and 2.3, Darwin do so.
                 */
                if ((command >> AGPSTAT_RQ_DEPTH_SHIFT) > 7)
@@ -398,6 +369,7 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
        int i;
        void *temp;
        struct page *page;
+       struct page **pages;
 
        /* We can't handle 2 level gatt's */
        if (bridge->driver->size_type == LVL2_APER_SIZE)
@@ -426,21 +398,39 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
        if (table == NULL)
                return -ENOMEM;
 
+       pages = kmalloc((1 << page_order) * sizeof(struct page*), GFP_KERNEL);
+       if (pages == NULL)
+               goto enomem;
+
        table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
 
-       for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
+       for (page = virt_to_page(table), i = 0; page <= virt_to_page(table_end);
+            page++, i++) {
                SetPageReserved(page);
+               pages[i] = page;
+       }
 
        bridge->gatt_table_real = (u32 *) table;
-       bridge->gatt_table = (u32 *)table;
-       bridge->gatt_bus_addr = virt_to_gart(table);
+       /* Need to clear out any dirty data still sitting in caches */
+       flush_dcache_range((unsigned long)table,
+                          (unsigned long)(table_end + PAGE_SIZE));
+       bridge->gatt_table = vmap(pages, (1 << page_order), 0, PAGE_KERNEL_NCG);
+
+       if (bridge->gatt_table == NULL)
+               goto enomem;
+
+       bridge->gatt_bus_addr = virt_to_phys(table);
 
        for (i = 0; i < num_entries; i++)
                bridge->gatt_table[i] = 0;
 
-       flush_dcache_range((unsigned long)table, (unsigned long)table_end);
-
        return 0;
+
+enomem:
+       kfree(pages);
+       if (table)
+               free_pages((unsigned long)table, page_order);
+       return -ENOMEM;
 }
 
 static int uninorth_free_gatt_table(struct agp_bridge_data *bridge)
@@ -458,6 +448,7 @@ static int uninorth_free_gatt_table(struct agp_bridge_data *bridge)
         * from the table.
         */
 
+       vunmap(bridge->gatt_table);
        table = (char *) bridge->gatt_table_real;
        table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
 
@@ -519,7 +510,7 @@ const struct agp_bridge_driver uninorth_agp_driver = {
        .create_gatt_table      = uninorth_create_gatt_table,
        .free_gatt_table        = uninorth_free_gatt_table,
        .insert_memory          = uninorth_insert_memory,
-       .remove_memory          = agp_generic_remove_memory,
+       .remove_memory          = uninorth_remove_memory,
        .alloc_by_type          = agp_generic_alloc_by_type,
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
@@ -545,8 +536,8 @@ const struct agp_bridge_driver u3_agp_driver = {
        .agp_enable             = uninorth_agp_enable,
        .create_gatt_table      = uninorth_create_gatt_table,
        .free_gatt_table        = uninorth_free_gatt_table,
-       .insert_memory          = u3_insert_memory,
-       .remove_memory          = u3_remove_memory,
+       .insert_memory          = uninorth_insert_memory,
+       .remove_memory          = uninorth_remove_memory,
        .alloc_by_type          = agp_generic_alloc_by_type,
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,