agp: generic_alloc_pages()
authorShaohua Li <shaohua.li@intel.com>
Thu, 21 Aug 2008 02:46:11 +0000 (10:46 +0800)
committerIngo Molnar <mingo@elte.hu>
Thu, 21 Aug 2008 11:47:46 +0000 (13:47 +0200)
Add agp_generic_alloc_pages(), it uses new pageattr array interface API.

Signed-off-by: Dave Airlie <airlied@gmail.com>
Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
drivers/char/agp/agp.h
drivers/char/agp/generic.c
drivers/char/agp/intel-agp.c

index 81e14bea54bdb8779e7b6f0cc4f468e7bb51b3a2..55d2c9d141779ddbe3c0a590aa10147947fc2bc5 100644 (file)
@@ -116,6 +116,7 @@ struct agp_bridge_driver {
        struct agp_memory *(*alloc_by_type) (size_t, int);
        void (*free_by_type)(struct agp_memory *);
        void *(*agp_alloc_page)(struct agp_bridge_data *);
+       int (*agp_alloc_pages)(struct agp_bridge_data *, struct agp_memory *, size_t);
        void (*agp_destroy_page)(void *, int flags);
        int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
        void (*chipset_flush)(struct agp_bridge_data *);
@@ -274,6 +275,8 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type);
 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);
+int agp_generic_alloc_pages(struct agp_bridge_data *agp_bridge,
+                           struct agp_memory *memory, size_t page_count);
 void agp_generic_destroy_page(void *addr, int flags);
 void agp_free_key(int key);
 int agp_num_entries(void);
index eaa1a355bb326a483b270689347fc49a80cbe05a..13a5577ee434a631de2f50a9f032720e1b2fdbfd 100644 (file)
@@ -264,6 +264,15 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
        if (new == NULL)
                return NULL;
 
+       if (bridge->driver->agp_alloc_pages) {
+               if (bridge->driver->agp_alloc_pages(bridge, new, page_count)) {
+                       agp_free_memory(new);
+                       return NULL;
+               }
+               new->bridge = bridge;
+               return new;
+       }
+
        for (i = 0; i < page_count; i++) {
                void *addr = bridge->driver->agp_alloc_page(bridge);
 
@@ -1178,6 +1187,39 @@ EXPORT_SYMBOL(agp_generic_alloc_user);
  * against a maximum value.
  */
 
+int agp_generic_alloc_pages(struct agp_bridge_data *bridge, struct agp_memory *mem, size_t num_pages)
+{
+       struct page * page;
+       int i, ret = -ENOMEM;
+
+       for (i = 0; i < num_pages; i++) {
+               page = alloc_page(GFP_KERNEL | GFP_DMA32);
+               /* agp_free_memory() needs gart address */
+               if (page == NULL)
+                       goto out;
+
+#ifndef CONFIG_X86
+               map_page_into_agp(page);
+#endif
+               get_page(page);
+               atomic_inc(&agp_bridge->current_memory_agp);
+
+               /* set_memory_array_uc() needs virtual address */
+               mem->memory[i] = (unsigned long)page_address(page);
+               mem->page_count++;
+       }
+
+#ifdef CONFIG_X86
+       set_memory_array_uc(mem->memory, num_pages);
+#endif
+       ret = 0;
+out:
+       for (i = 0; i < mem->page_count; i++)
+               mem->memory[i] = virt_to_gart((void *)mem->memory[i]);
+       return ret;
+}
+EXPORT_SYMBOL(agp_generic_alloc_pages);
+
 void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
 {
        struct page * page;
index df702642ab8fb49334ae46c0f0125df4a735376c..2cff0976a668d189e7d40aaa37f16e98ecf1756e 100644 (file)
@@ -1703,6 +1703,7 @@ static const struct agp_bridge_driver intel_generic_driver = {
        .alloc_by_type          = agp_generic_alloc_by_type,
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
@@ -1728,6 +1729,7 @@ static const struct agp_bridge_driver intel_810_driver = {
        .alloc_by_type          = intel_i810_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
@@ -1752,6 +1754,7 @@ static const struct agp_bridge_driver intel_815_driver = {
        .alloc_by_type          = agp_generic_alloc_by_type,
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
@@ -1777,6 +1780,7 @@ static const struct agp_bridge_driver intel_830_driver = {
        .alloc_by_type          = intel_i830_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
        .chipset_flush          = intel_i830_chipset_flush,
@@ -1802,6 +1806,7 @@ static const struct agp_bridge_driver intel_820_driver = {
        .alloc_by_type          = agp_generic_alloc_by_type,
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
@@ -1826,6 +1831,7 @@ static const struct agp_bridge_driver intel_830mp_driver = {
        .alloc_by_type          = agp_generic_alloc_by_type,
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
@@ -1850,6 +1856,7 @@ static const struct agp_bridge_driver intel_840_driver = {
        .alloc_by_type          = agp_generic_alloc_by_type,
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
@@ -1874,6 +1881,7 @@ static const struct agp_bridge_driver intel_845_driver = {
        .alloc_by_type          = agp_generic_alloc_by_type,
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
        .chipset_flush          = intel_i830_chipset_flush,
@@ -1899,6 +1907,7 @@ static const struct agp_bridge_driver intel_850_driver = {
        .alloc_by_type          = agp_generic_alloc_by_type,
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
@@ -1923,6 +1932,7 @@ static const struct agp_bridge_driver intel_860_driver = {
        .alloc_by_type          = agp_generic_alloc_by_type,
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
@@ -1948,6 +1958,7 @@ static const struct agp_bridge_driver intel_915_driver = {
        .alloc_by_type          = intel_i830_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
        .chipset_flush          = intel_i915_chipset_flush,
@@ -1974,6 +1985,7 @@ static const struct agp_bridge_driver intel_i965_driver = {
        .alloc_by_type          = intel_i830_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
        .chipset_flush          = intel_i915_chipset_flush,
@@ -1999,6 +2011,7 @@ static const struct agp_bridge_driver intel_7505_driver = {
        .alloc_by_type          = agp_generic_alloc_by_type,
        .free_by_type           = agp_generic_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
@@ -2024,6 +2037,7 @@ static const struct agp_bridge_driver intel_g33_driver = {
        .alloc_by_type          = intel_i830_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
        .chipset_flush          = intel_i915_chipset_flush,