agp: add chipset flushing support to AGP interface

This bumps the AGP interface to 0.103.

Certain Intel chipsets contains a global write buffer, and this can require
flushing from the drm or X.org to make sure all data has hit RAM before
initiating a GPU transfer, due to a lack of coherency with the integrated
graphics device and this buffer.

This just adds generic support to the AGP interfaces, a follow-on patch
will add support to the Intel driver to use this interface.

Signed-off-by: Dave Airlie <airlied@redhat.com>

authored by Dave Airlie and committed by Dave Airlie a13af4b4 9ef9dc69

+29 -2
+2 -1
drivers/char/agp/agp.h
··· 117 void (*free_by_type)(struct agp_memory *); 118 void *(*agp_alloc_page)(struct agp_bridge_data *); 119 void (*agp_destroy_page)(void *, int flags); 120 - int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); 121 }; 122 123 struct agp_bridge_data {
··· 117 void (*free_by_type)(struct agp_memory *); 118 void *(*agp_alloc_page)(struct agp_bridge_data *); 119 void (*agp_destroy_page)(void *, int flags); 120 + int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); 121 + void (*chipset_flush)(struct agp_bridge_data *); 122 }; 123 124 struct agp_bridge_data {
+1 -1
drivers/char/agp/backend.c
··· 43 * fix some real stupidity. It's only by chance we can bump 44 * past 0.99 at all due to some boolean logic error. */ 45 #define AGPGART_VERSION_MAJOR 0 46 - #define AGPGART_VERSION_MINOR 102 47 static const struct agp_version agp_current_version = 48 { 49 .major = AGPGART_VERSION_MAJOR,
··· 43 * fix some real stupidity. It's only by chance we can bump 44 * past 0.99 at all due to some boolean logic error. */ 45 #define AGPGART_VERSION_MAJOR 0 46 + #define AGPGART_VERSION_MINOR 103 47 static const struct agp_version agp_current_version = 48 { 49 .major = AGPGART_VERSION_MAJOR,
+4
drivers/char/agp/compat_ioctl.c
··· 273 case AGPIOC_UNBIND32: 274 ret_val = compat_agpioc_unbind_wrap(curr_priv, (void __user *) arg); 275 break; 276 } 277 278 ioctl_out:
··· 273 case AGPIOC_UNBIND32: 274 ret_val = compat_agpioc_unbind_wrap(curr_priv, (void __user *) arg); 275 break; 276 + 277 + case AGPIOC_CHIPSET_FLUSH32: 278 + ret_val = agpioc_chipset_flush_wrap(curr_priv); 279 + break; 280 } 281 282 ioctl_out:
+2
drivers/char/agp/compat_ioctl.h
··· 39 #define AGPIOC_DEALLOCATE32 _IOW (AGPIOC_BASE, 7, compat_int_t) 40 #define AGPIOC_BIND32 _IOW (AGPIOC_BASE, 8, compat_uptr_t) 41 #define AGPIOC_UNBIND32 _IOW (AGPIOC_BASE, 9, compat_uptr_t) 42 43 struct agp_info32 { 44 struct agp_version version; /* version of the driver */ ··· 102 struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type); 103 struct agp_memory *agp_find_mem_by_key(int key); 104 struct agp_client *agp_find_client_by_pid(pid_t id); 105 106 #endif /* _AGP_COMPAT_H */
··· 39 #define AGPIOC_DEALLOCATE32 _IOW (AGPIOC_BASE, 7, compat_int_t) 40 #define AGPIOC_BIND32 _IOW (AGPIOC_BASE, 8, compat_uptr_t) 41 #define AGPIOC_UNBIND32 _IOW (AGPIOC_BASE, 9, compat_uptr_t) 42 + #define AGPIOC_CHIPSET_FLUSH32 _IO (AGPIOC_BASE, 10) 43 44 struct agp_info32 { 45 struct agp_version version; /* version of the driver */ ··· 101 struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type); 102 struct agp_memory *agp_find_mem_by_key(int key); 103 struct agp_client *agp_find_client_by_pid(pid_t id); 104 + int agpioc_chipset_flush_wrap(struct agp_file_private *priv); 105 106 #endif /* _AGP_COMPAT_H */
+11
drivers/char/agp/frontend.c
··· 960 return agp_unbind_memory(memory); 961 } 962 963 static int agp_ioctl(struct inode *inode, struct file *file, 964 unsigned int cmd, unsigned long arg) 965 { ··· 1039 1040 case AGPIOC_UNBIND: 1041 ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg); 1042 break; 1043 } 1044
··· 960 return agp_unbind_memory(memory); 961 } 962 963 + int agpioc_chipset_flush_wrap(struct agp_file_private *priv) 964 + { 965 + DBG(""); 966 + agp_flush_chipset(agp_bridge); 967 + return 0; 968 + } 969 + 970 static int agp_ioctl(struct inode *inode, struct file *file, 971 unsigned int cmd, unsigned long arg) 972 { ··· 1032 1033 case AGPIOC_UNBIND: 1034 ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg); 1035 + break; 1036 + 1037 + case AGPIOC_CHIPSET_FLUSH: 1038 + ret_val = agpioc_chipset_flush_wrap(curr_priv); 1039 break; 1040 } 1041
+7
drivers/char/agp/generic.c
··· 80 return -1; 81 } 82 83 /* 84 * Use kmalloc if possible for the page list. Otherwise fall back to 85 * vmalloc. This speeds things up and also saves memory for small AGP
··· 80 return -1; 81 } 82 83 + void agp_flush_chipset(struct agp_bridge_data *bridge) 84 + { 85 + if (bridge->driver->chipset_flush) 86 + bridge->driver->chipset_flush(bridge); 87 + } 88 + EXPORT_SYMBOL(agp_flush_chipset); 89 + 90 /* 91 * Use kmalloc if possible for the page list. Otherwise fall back to 92 * vmalloc. This speeds things up and also saves memory for small AGP
+1
include/linux/agp_backend.h
··· 109 extern void agp_enable(struct agp_bridge_data *, u32); 110 extern struct agp_bridge_data *agp_backend_acquire(struct pci_dev *); 111 extern void agp_backend_release(struct agp_bridge_data *); 112 113 #endif /* __KERNEL__ */ 114 #endif /* _AGP_BACKEND_H */
··· 109 extern void agp_enable(struct agp_bridge_data *, u32); 110 extern struct agp_bridge_data *agp_backend_acquire(struct pci_dev *); 111 extern void agp_backend_release(struct agp_bridge_data *); 112 + extern void agp_flush_chipset(struct agp_bridge_data *); 113 114 #endif /* __KERNEL__ */ 115 #endif /* _AGP_BACKEND_H */
+1
include/linux/agpgart.h
··· 38 #define AGPIOC_DEALLOCATE _IOW (AGPIOC_BASE, 7, int) 39 #define AGPIOC_BIND _IOW (AGPIOC_BASE, 8, struct agp_bind*) 40 #define AGPIOC_UNBIND _IOW (AGPIOC_BASE, 9, struct agp_unbind*) 41 42 #define AGP_DEVICE "/dev/agpgart" 43
··· 38 #define AGPIOC_DEALLOCATE _IOW (AGPIOC_BASE, 7, int) 39 #define AGPIOC_BIND _IOW (AGPIOC_BASE, 8, struct agp_bind*) 40 #define AGPIOC_UNBIND _IOW (AGPIOC_BASE, 9, struct agp_unbind*) 41 + #define AGPIOC_CHIPSET_FLUSH _IO (AGPIOC_BASE, 10) 42 43 #define AGP_DEVICE "/dev/agpgart" 44