diff options
Diffstat (limited to 'drivers/char/drm/drm_scatter.c')
-rw-r--r-- | drivers/char/drm/drm_scatter.c | 183 |
1 files changed, 87 insertions, 96 deletions
diff --git a/drivers/char/drm/drm_scatter.c b/drivers/char/drm/drm_scatter.c index ed267d49bc6a..ce81bf248200 100644 --- a/drivers/char/drm/drm_scatter.c +++ b/drivers/char/drm/drm_scatter.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * \file drm_scatter.h | 2 | * \file drm_scatter.c |
3 | * IOCTLs to manage scatter/gather memory | 3 | * IOCTLs to manage scatter/gather memory |
4 | * | 4 | * |
5 | * \author Gareth Hughes <gareth@valinux.com> | 5 | * \author Gareth Hughes <gareth@valinux.com> |
@@ -37,28 +37,24 @@ | |||
37 | 37 | ||
38 | #define DEBUG_SCATTER 0 | 38 | #define DEBUG_SCATTER 0 |
39 | 39 | ||
40 | void drm_sg_cleanup( drm_sg_mem_t *entry ) | 40 | void drm_sg_cleanup(drm_sg_mem_t * entry) |
41 | { | 41 | { |
42 | struct page *page; | 42 | struct page *page; |
43 | int i; | 43 | int i; |
44 | 44 | ||
45 | for ( i = 0 ; i < entry->pages ; i++ ) { | 45 | for (i = 0; i < entry->pages; i++) { |
46 | page = entry->pagelist[i]; | 46 | page = entry->pagelist[i]; |
47 | if ( page ) | 47 | if (page) |
48 | ClearPageReserved( page ); | 48 | ClearPageReserved(page); |
49 | } | 49 | } |
50 | 50 | ||
51 | vfree( entry->virtual ); | 51 | vfree(entry->virtual); |
52 | 52 | ||
53 | drm_free( entry->busaddr, | 53 | drm_free(entry->busaddr, |
54 | entry->pages * sizeof(*entry->busaddr), | 54 | entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES); |
55 | DRM_MEM_PAGES ); | 55 | drm_free(entry->pagelist, |
56 | drm_free( entry->pagelist, | 56 | entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES); |
57 | entry->pages * sizeof(*entry->pagelist), | 57 | drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS); |
58 | DRM_MEM_PAGES ); | ||
59 | drm_free( entry, | ||
60 | sizeof(*entry), | ||
61 | DRM_MEM_SGLISTS ); | ||
62 | } | 58 | } |
63 | 59 | ||
64 | #ifdef _LP64 | 60 | #ifdef _LP64 |
@@ -67,8 +63,8 @@ void drm_sg_cleanup( drm_sg_mem_t *entry ) | |||
67 | # define ScatterHandle(x) (unsigned int)(x) | 63 | # define ScatterHandle(x) (unsigned int)(x) |
68 | #endif | 64 | #endif |
69 | 65 | ||
70 | int drm_sg_alloc( struct inode *inode, struct file *filp, | 66 | int drm_sg_alloc(struct inode *inode, struct file *filp, |
71 | unsigned int cmd, unsigned long arg ) | 67 | unsigned int cmd, unsigned long arg) |
72 | { | 68 | { |
73 | drm_file_t *priv = filp->private_data; | 69 | drm_file_t *priv = filp->private_data; |
74 | drm_device_t *dev = priv->head->dev; | 70 | drm_device_t *dev = priv->head->dev; |
@@ -77,75 +73,70 @@ int drm_sg_alloc( struct inode *inode, struct file *filp, | |||
77 | drm_sg_mem_t *entry; | 73 | drm_sg_mem_t *entry; |
78 | unsigned long pages, i, j; | 74 | unsigned long pages, i, j; |
79 | 75 | ||
80 | DRM_DEBUG( "%s\n", __FUNCTION__ ); | 76 | DRM_DEBUG("%s\n", __FUNCTION__); |
81 | 77 | ||
82 | if (!drm_core_check_feature(dev, DRIVER_SG)) | 78 | if (!drm_core_check_feature(dev, DRIVER_SG)) |
83 | return -EINVAL; | 79 | return -EINVAL; |
84 | 80 | ||
85 | if ( dev->sg ) | 81 | if (dev->sg) |
86 | return -EINVAL; | 82 | return -EINVAL; |
87 | 83 | ||
88 | if ( copy_from_user( &request, argp, sizeof(request) ) ) | 84 | if (copy_from_user(&request, argp, sizeof(request))) |
89 | return -EFAULT; | 85 | return -EFAULT; |
90 | 86 | ||
91 | entry = drm_alloc( sizeof(*entry), DRM_MEM_SGLISTS ); | 87 | entry = drm_alloc(sizeof(*entry), DRM_MEM_SGLISTS); |
92 | if ( !entry ) | 88 | if (!entry) |
93 | return -ENOMEM; | 89 | return -ENOMEM; |
94 | 90 | ||
95 | memset( entry, 0, sizeof(*entry) ); | 91 | memset(entry, 0, sizeof(*entry)); |
96 | 92 | ||
97 | pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; | 93 | pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; |
98 | DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages ); | 94 | DRM_DEBUG("sg size=%ld pages=%ld\n", request.size, pages); |
99 | 95 | ||
100 | entry->pages = pages; | 96 | entry->pages = pages; |
101 | entry->pagelist = drm_alloc( pages * sizeof(*entry->pagelist), | 97 | entry->pagelist = drm_alloc(pages * sizeof(*entry->pagelist), |
102 | DRM_MEM_PAGES ); | 98 | DRM_MEM_PAGES); |
103 | if ( !entry->pagelist ) { | 99 | if (!entry->pagelist) { |
104 | drm_free( entry, sizeof(*entry), DRM_MEM_SGLISTS ); | 100 | drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS); |
105 | return -ENOMEM; | 101 | return -ENOMEM; |
106 | } | 102 | } |
107 | 103 | ||
108 | memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist)); | 104 | memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist)); |
109 | 105 | ||
110 | entry->busaddr = drm_alloc( pages * sizeof(*entry->busaddr), | 106 | entry->busaddr = drm_alloc(pages * sizeof(*entry->busaddr), |
111 | DRM_MEM_PAGES ); | 107 | DRM_MEM_PAGES); |
112 | if ( !entry->busaddr ) { | 108 | if (!entry->busaddr) { |
113 | drm_free( entry->pagelist, | 109 | drm_free(entry->pagelist, |
114 | entry->pages * sizeof(*entry->pagelist), | 110 | entry->pages * sizeof(*entry->pagelist), |
115 | DRM_MEM_PAGES ); | 111 | DRM_MEM_PAGES); |
116 | drm_free( entry, | 112 | drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS); |
117 | sizeof(*entry), | ||
118 | DRM_MEM_SGLISTS ); | ||
119 | return -ENOMEM; | 113 | return -ENOMEM; |
120 | } | 114 | } |
121 | memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) ); | 115 | memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr)); |
122 | 116 | ||
123 | entry->virtual = vmalloc_32( pages << PAGE_SHIFT ); | 117 | entry->virtual = vmalloc_32(pages << PAGE_SHIFT); |
124 | if ( !entry->virtual ) { | 118 | if (!entry->virtual) { |
125 | drm_free( entry->busaddr, | 119 | drm_free(entry->busaddr, |
126 | entry->pages * sizeof(*entry->busaddr), | 120 | entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES); |
127 | DRM_MEM_PAGES ); | 121 | drm_free(entry->pagelist, |
128 | drm_free( entry->pagelist, | 122 | entry->pages * sizeof(*entry->pagelist), |
129 | entry->pages * sizeof(*entry->pagelist), | 123 | DRM_MEM_PAGES); |
130 | DRM_MEM_PAGES ); | 124 | drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS); |
131 | drm_free( entry, | ||
132 | sizeof(*entry), | ||
133 | DRM_MEM_SGLISTS ); | ||
134 | return -ENOMEM; | 125 | return -ENOMEM; |
135 | } | 126 | } |
136 | 127 | ||
137 | /* This also forces the mapping of COW pages, so our page list | 128 | /* This also forces the mapping of COW pages, so our page list |
138 | * will be valid. Please don't remove it... | 129 | * will be valid. Please don't remove it... |
139 | */ | 130 | */ |
140 | memset( entry->virtual, 0, pages << PAGE_SHIFT ); | 131 | memset(entry->virtual, 0, pages << PAGE_SHIFT); |
141 | 132 | ||
142 | entry->handle = ScatterHandle((unsigned long)entry->virtual); | 133 | entry->handle = ScatterHandle((unsigned long)entry->virtual); |
143 | 134 | ||
144 | DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle ); | 135 | DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle); |
145 | DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual ); | 136 | DRM_DEBUG("sg alloc virtual = %p\n", entry->virtual); |
146 | 137 | ||
147 | for (i = (unsigned long)entry->virtual, j = 0; j < pages; | 138 | for (i = (unsigned long)entry->virtual, j = 0; j < pages; |
148 | i += PAGE_SIZE, j++) { | 139 | i += PAGE_SIZE, j++) { |
149 | entry->pagelist[j] = vmalloc_to_page((void *)i); | 140 | entry->pagelist[j] = vmalloc_to_page((void *)i); |
150 | if (!entry->pagelist[j]) | 141 | if (!entry->pagelist[j]) |
151 | goto failed; | 142 | goto failed; |
@@ -154,8 +145,8 @@ int drm_sg_alloc( struct inode *inode, struct file *filp, | |||
154 | 145 | ||
155 | request.handle = entry->handle; | 146 | request.handle = entry->handle; |
156 | 147 | ||
157 | if ( copy_to_user( argp, &request, sizeof(request) ) ) { | 148 | if (copy_to_user(argp, &request, sizeof(request))) { |
158 | drm_sg_cleanup( entry ); | 149 | drm_sg_cleanup(entry); |
159 | return -EFAULT; | 150 | return -EFAULT; |
160 | } | 151 | } |
161 | 152 | ||
@@ -166,50 +157,50 @@ int drm_sg_alloc( struct inode *inode, struct file *filp, | |||
166 | * versa. | 157 | * versa. |
167 | */ | 158 | */ |
168 | { | 159 | { |
169 | int error = 0; | 160 | int error = 0; |
170 | 161 | ||
171 | for ( i = 0 ; i < pages ; i++ ) { | 162 | for (i = 0; i < pages; i++) { |
172 | unsigned long *tmp; | 163 | unsigned long *tmp; |
173 | 164 | ||
174 | tmp = page_address( entry->pagelist[i] ); | 165 | tmp = page_address(entry->pagelist[i]); |
175 | for ( j = 0 ; | 166 | for (j = 0; |
176 | j < PAGE_SIZE / sizeof(unsigned long) ; | 167 | j < PAGE_SIZE / sizeof(unsigned long); |
177 | j++, tmp++ ) { | 168 | j++, tmp++) { |
178 | *tmp = 0xcafebabe; | 169 | *tmp = 0xcafebabe; |
179 | } | 170 | } |
180 | tmp = (unsigned long *)((u8 *)entry->virtual + | 171 | tmp = (unsigned long *)((u8 *) entry->virtual + |
181 | (PAGE_SIZE * i)); | 172 | (PAGE_SIZE * i)); |
182 | for( j = 0 ; | 173 | for (j = 0; |
183 | j < PAGE_SIZE / sizeof(unsigned long) ; | 174 | j < PAGE_SIZE / sizeof(unsigned long); |
184 | j++, tmp++ ) { | 175 | j++, tmp++) { |
185 | if ( *tmp != 0xcafebabe && error == 0 ) { | 176 | if (*tmp != 0xcafebabe && error == 0) { |
186 | error = 1; | 177 | error = 1; |
187 | DRM_ERROR( "Scatter allocation error, " | 178 | DRM_ERROR("Scatter allocation error, " |
188 | "pagelist does not match " | 179 | "pagelist does not match " |
189 | "virtual mapping\n" ); | 180 | "virtual mapping\n"); |
181 | } | ||
182 | } | ||
183 | tmp = page_address(entry->pagelist[i]); | ||
184 | for (j = 0; | ||
185 | j < PAGE_SIZE / sizeof(unsigned long); | ||
186 | j++, tmp++) { | ||
187 | *tmp = 0; | ||
190 | } | 188 | } |
191 | } | 189 | } |
192 | tmp = page_address( entry->pagelist[i] ); | 190 | if (error == 0) |
193 | for(j = 0 ; | 191 | DRM_ERROR("Scatter allocation matches pagelist\n"); |
194 | j < PAGE_SIZE / sizeof(unsigned long) ; | ||
195 | j++, tmp++) { | ||
196 | *tmp = 0; | ||
197 | } | ||
198 | } | ||
199 | if (error == 0) | ||
200 | DRM_ERROR( "Scatter allocation matches pagelist\n" ); | ||
201 | } | 192 | } |
202 | #endif | 193 | #endif |
203 | 194 | ||
204 | return 0; | 195 | return 0; |
205 | 196 | ||
206 | failed: | 197 | failed: |
207 | drm_sg_cleanup( entry ); | 198 | drm_sg_cleanup(entry); |
208 | return -ENOMEM; | 199 | return -ENOMEM; |
209 | } | 200 | } |
210 | 201 | ||
211 | int drm_sg_free( struct inode *inode, struct file *filp, | 202 | int drm_sg_free(struct inode *inode, struct file *filp, |
212 | unsigned int cmd, unsigned long arg ) | 203 | unsigned int cmd, unsigned long arg) |
213 | { | 204 | { |
214 | drm_file_t *priv = filp->private_data; | 205 | drm_file_t *priv = filp->private_data; |
215 | drm_device_t *dev = priv->head->dev; | 206 | drm_device_t *dev = priv->head->dev; |
@@ -219,20 +210,20 @@ int drm_sg_free( struct inode *inode, struct file *filp, | |||
219 | if (!drm_core_check_feature(dev, DRIVER_SG)) | 210 | if (!drm_core_check_feature(dev, DRIVER_SG)) |
220 | return -EINVAL; | 211 | return -EINVAL; |
221 | 212 | ||
222 | if ( copy_from_user( &request, | 213 | if (copy_from_user(&request, |
223 | (drm_scatter_gather_t __user *)arg, | 214 | (drm_scatter_gather_t __user *) arg, |
224 | sizeof(request) ) ) | 215 | sizeof(request))) |
225 | return -EFAULT; | 216 | return -EFAULT; |
226 | 217 | ||
227 | entry = dev->sg; | 218 | entry = dev->sg; |
228 | dev->sg = NULL; | 219 | dev->sg = NULL; |
229 | 220 | ||
230 | if ( !entry || entry->handle != request.handle ) | 221 | if (!entry || entry->handle != request.handle) |
231 | return -EINVAL; | 222 | return -EINVAL; |
232 | 223 | ||
233 | DRM_DEBUG( "sg free virtual = %p\n", entry->virtual ); | 224 | DRM_DEBUG("sg free virtual = %p\n", entry->virtual); |
234 | 225 | ||
235 | drm_sg_cleanup( entry ); | 226 | drm_sg_cleanup(entry); |
236 | 227 | ||
237 | return 0; | 228 | return 0; |
238 | } | 229 | } |