| @@ -1,336 +1,339 @@ | | | @@ -1,336 +1,339 @@ |
1 | /* $NetBSD: drm_memory.c,v 1.1.2.2 2013/07/24 02:39:25 riastradh Exp $ */ | | 1 | /* $NetBSD: drm_memory.c,v 1.1.2.3 2013/07/24 02:47:19 riastradh Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2013 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2013 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Taylor R. Campbell. | | 8 | * by Taylor R. Campbell. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: drm_memory.c,v 1.1.2.2 2013/07/24 02:39:25 riastradh Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: drm_memory.c,v 1.1.2.3 2013/07/24 02:47:19 riastradh Exp $"); |
34 | | | 34 | |
35 | /* XXX Cargo-culted from the old drm_memory.c. */ | | 35 | /* XXX Cargo-culted from the old drm_memory.c. */ |
36 | | | 36 | |
37 | #ifdef _KERNEL_OPT | | 37 | #ifdef _KERNEL_OPT |
38 | #include "agp_i810.h" | | 38 | #include "agp_i810.h" |
39 | #include "genfb.h" | | 39 | #include "genfb.h" |
40 | #else | | 40 | #else |
41 | #define NAGP_I810 1 /* XXX WTF? */ | | 41 | #define NAGP_I810 1 /* XXX WTF? */ |
42 | #define NGENFB 0 /* XXX WTF? */ | | 42 | #define NGENFB 0 /* XXX WTF? */ |
43 | #endif | | 43 | #endif |
44 | | | 44 | |
45 | #include <sys/bus.h> | | 45 | #include <sys/bus.h> |
46 | | | 46 | |
47 | #if NAGP_I810 > 0 | | 47 | #if NAGP_I810 > 0 |
48 | /* XXX include order botch -- shouldn't need to include pcivar.h */ | | 48 | /* XXX include order botch -- shouldn't need to include pcivar.h */ |
49 | #include <dev/pci/pcivar.h> | | 49 | #include <dev/pci/pcivar.h> |
50 | #include <dev/pci/agpvar.h> | | 50 | #include <dev/pci/agpvar.h> |
51 | #endif | | 51 | #endif |
52 | | | 52 | |
53 | #if NGENFB > 0 | | 53 | #if NGENFB > 0 |
54 | #include <dev/wsfb/genfbvar.h> | | 54 | #include <dev/wsfb/genfbvar.h> |
55 | #endif | | 55 | #endif |
56 | | | 56 | |
57 | #include <drm/drmP.h> | | 57 | #include <drm/drmP.h> |
58 | | | 58 | |
59 | /* | | 59 | /* |
60 | * XXX drm_bus_borrow is a horrible kludge! | | 60 | * XXX drm_bus_borrow is a horrible kludge! |
61 | */ | | 61 | */ |
62 | static bool | | 62 | static bool |
63 | drm_bus_borrow(bus_addr_t base, bus_space_handle_t *handlep) | | 63 | drm_bus_borrow(bus_addr_t base, bus_space_handle_t *handlep) |
64 | { | | 64 | { |
65 | | | 65 | |
66 | #if NAGP_I810 > 0 | | 66 | #if NAGP_I810 > 0 |
67 | if (agp_i810_borrow(base, handlep)) | | 67 | if (agp_i810_borrow(base, handlep)) |
68 | return true; | | 68 | return true; |
69 | #endif | | 69 | #endif |
70 | | | 70 | |
71 | #if NGENFB > 0 | | 71 | #if NGENFB > 0 |
72 | if (genfb_borrow(base, handlep)) | | 72 | if (genfb_borrow(base, handlep)) |
73 | return true; | | 73 | return true; |
74 | #endif | | 74 | #endif |
75 | | | 75 | |
76 | return false; | | 76 | return false; |
77 | } | | 77 | } |
78 | | | 78 | |
79 | void * | | 79 | void * |
80 | drm_ioremap(struct drm_device *dev, struct drm_local_map *map) | | 80 | drm_ioremap(struct drm_device *dev, struct drm_local_map *map) |
81 | { | | 81 | { |
82 | const bus_space_tag_t bst = dev->bst; | | 82 | const bus_space_tag_t bst = dev->bst; |
83 | unsigned int unit; | | 83 | unsigned int unit; |
84 | int error; | | 84 | int error; |
85 | | | 85 | |
86 | /* | | 86 | /* |
87 | * Search dev's bus maps for a match. | | 87 | * Search dev's bus maps for a match. |
88 | */ | | 88 | */ |
89 | for (unit = 0; unit < dev->bus_nmaps; unit++) { | | 89 | for (unit = 0; unit < dev->bus_nmaps; unit++) { |
90 | struct drm_bus_map *const bm = &dev->bus_maps[unit]; | | 90 | struct drm_bus_map *const bm = &dev->bus_maps[unit]; |
91 | | | 91 | |
92 | /* Reject maps starting after the request. */ | | 92 | /* Reject maps starting after the request. */ |
93 | if (map->offset < bm->bm_base) | | 93 | if (map->offset < bm->bm_base) |
94 | continue; | | 94 | continue; |
95 | | | 95 | |
96 | /* Reject maps smaller than the request. */ | | 96 | /* Reject maps smaller than the request. */ |
97 | if (bm->bm_size < map->size) | | 97 | if (bm->bm_size < map->size) |
98 | continue; | | 98 | continue; |
99 | | | 99 | |
100 | /* | | 100 | /* |
101 | * Reject maps that the request doesn't fit in. (Make | | 101 | * Reject maps that the request doesn't fit in. (Make |
102 | * sure to avoid integer overflow.) | | 102 | * sure to avoid integer overflow.) |
103 | */ | | 103 | */ |
104 | if ((bm->bm_size - map->size) < | | 104 | if ((bm->bm_size - map->size) < |
105 | (map->offset - bm->bm_base)) | | 105 | (map->offset - bm->bm_base)) |
106 | continue; | | 106 | continue; |
107 | | | 107 | |
108 | /* Has it been mapped yet? If not, map it. */ | | 108 | /* Has it been mapped yet? If not, map it. */ |
109 | if (bm->bm_mapped == 0) { | | 109 | if (bm->bm_mapped == 0) { |
110 | KASSERT(ISSET(bm->bm_flags, BUS_SPACE_MAP_LINEAR)); | | 110 | KASSERT(ISSET(bm->bm_flags, BUS_SPACE_MAP_LINEAR)); |
111 | error = bus_space_map(bst, bm->bm_base, | | 111 | error = bus_space_map(bst, bm->bm_base, |
112 | bm->bm_size, bm->bm_flags, &bm->bm_bsh); | | 112 | bm->bm_size, bm->bm_flags, &bm->bm_bsh); |
113 | if (error) { | | 113 | if (error) { |
114 | if (drm_bus_borrow(map->offset, &map->bsh)) { | | 114 | if (drm_bus_borrow(map->offset, |
115 | map->bus_map = NULL; | | 115 | &map->lm_data.bus_space.bsh)) { |
| | | 116 | map->lm_data.bus_space.bus_map = NULL; |
116 | goto win; | | 117 | goto win; |
117 | } | | 118 | } |
118 | return NULL; | | 119 | return NULL; |
119 | } | | 120 | } |
120 | } | | 121 | } |
121 | | | 122 | |
122 | /* Mark it used and make a subregion just for the request. */ | | 123 | /* Mark it used and make a subregion just for the request. */ |
123 | bm->bm_mapped++; | | 124 | bm->bm_mapped++; |
124 | error = bus_space_subregion(bst, bm->bm_bsh, | | 125 | error = bus_space_subregion(bst, bm->bm_bsh, |
125 | map->offset - bm->bm_base, map->size, &map->bsh); | | 126 | map->offset - bm->bm_base, map->size, |
| | | 127 | &map->lm_data.bus_space.bsh); |
126 | if (error) { | | 128 | if (error) { |
127 | /* | | 129 | /* |
128 | * Back out: unmark it and, if nobody else was | | 130 | * Back out: unmark it and, if nobody else was |
129 | * using it, unmap it. | | 131 | * using it, unmap it. |
130 | */ | | 132 | */ |
131 | if (--bm->bm_mapped == 0) | | 133 | if (--bm->bm_mapped == 0) |
132 | bus_space_unmap(bst, bm->bm_bsh, | | 134 | bus_space_unmap(bst, bm->bm_bsh, |
133 | bm->bm_size); | | 135 | bm->bm_size); |
134 | return NULL; | | 136 | return NULL; |
135 | } | | 137 | } |
136 | | | 138 | |
137 | /* Got it! */ | | 139 | /* Got it! */ |
138 | map->bus_map = bm; | | 140 | map->lm_data.bus_space.bus_map = bm; |
139 | goto win; | | 141 | goto win; |
140 | } | | 142 | } |
141 | | | 143 | |
142 | /* | | 144 | /* |
143 | * No dice. Try mapping it directly ourselves. | | 145 | * No dice. Try mapping it directly ourselves. |
144 | * | | 146 | * |
145 | * XXX Is this sensible? What prevents us from clobbering some | | 147 | * XXX Is this sensible? What prevents us from clobbering some |
146 | * existing map? And what does this have to do with agp? | | 148 | * existing map? And what does this have to do with agp? |
147 | */ | | 149 | */ |
148 | for (unit = 0; unit < dev->agp_nmaps; unit++) { | | 150 | for (unit = 0; unit < dev->agp_nmaps; unit++) { |
149 | struct drm_bus_map *const bm = &dev->agp_maps[unit]; | | 151 | struct drm_bus_map *const bm = &dev->agp_maps[unit]; |
150 | | | 152 | |
151 | /* Is this one allocated? */ | | 153 | /* Is this one allocated? */ |
152 | if (bm->bm_mapped > 0) { | | 154 | if (bm->bm_mapped > 0) { |
153 | /* | | 155 | /* |
154 | * Make sure it has the same base. | | 156 | * Make sure it has the same base. |
155 | * | | 157 | * |
156 | * XXX Why must it be the same base? Can't we | | 158 | * XXX Why must it be the same base? Can't we |
157 | * subregion here too? | | 159 | * subregion here too? |
158 | */ | | 160 | */ |
159 | if (bm->bm_base != map->offset) | | 161 | if (bm->bm_base != map->offset) |
160 | continue; | | 162 | continue; |
161 | | | 163 | |
162 | /* Make sure it's big enough. */ | | 164 | /* Make sure it's big enough. */ |
163 | if (bm->bm_size < map->size) | | 165 | if (bm->bm_size < map->size) |
164 | continue; | | 166 | continue; |
165 | | | 167 | |
166 | /* Mark it used and return it. */ | | 168 | /* Mark it used and return it. */ |
167 | bm->bm_mapped++; | | 169 | bm->bm_mapped++; |
168 | | | 170 | |
169 | /* XXX size is an input/output parameter too...? */ | | 171 | /* XXX size is an input/output parameter too...? */ |
170 | map->size = bm->bm_size; | | 172 | map->size = bm->bm_size; |
171 | | | 173 | |
172 | map->bsh = bm->bm_bsh; | | 174 | map->lm_data.bus_space.bsh = bm->bm_bsh; |
173 | map->bus_map = bm; | | 175 | map->lm_data.bus_space.bus_map = bm; |
174 | goto win; | | 176 | goto win; |
175 | } else { | | 177 | } else { |
176 | const int flags = BUS_SPACE_MAP_PREFETCHABLE | | | 178 | const int flags = BUS_SPACE_MAP_PREFETCHABLE | |
177 | BUS_SPACE_MAP_LINEAR; | | 179 | BUS_SPACE_MAP_LINEAR; |
178 | | | 180 | |
179 | /* Try mapping the request. */ | | 181 | /* Try mapping the request. */ |
180 | error = bus_space_map(bst, map->offset, map->size, | | 182 | error = bus_space_map(bst, map->offset, map->size, |
181 | flags, &bm->bm_bsh); | | 183 | flags, &bm->bm_bsh); |
182 | if (error) | | 184 | if (error) |
183 | return NULL; /* XXX Why not continue? */ | | 185 | return NULL; /* XXX Why not continue? */ |
184 | | | 186 | |
185 | /* Got it. Allocate this bus map. */ | | 187 | /* Got it. Allocate this bus map. */ |
186 | bm->bm_mapped++; | | 188 | bm->bm_mapped++; |
187 | bm->bm_base = map->offset; | | 189 | bm->bm_base = map->offset; |
188 | bm->bm_size = map->size; | | 190 | bm->bm_size = map->size; |
189 | bm->bm_flags = flags; /* XXX What for? */ | | 191 | bm->bm_flags = flags; /* XXX What for? */ |
190 | | | 192 | |
191 | map->bsh = bm->bm_bsh; | | 193 | map->lm_data.bus_space.bsh = bm->bm_bsh; |
192 | map->bus_map = bm; | | 194 | map->lm_data.bus_space.bus_map = bm; |
193 | goto win; | | 195 | goto win; |
194 | } | | 196 | } |
195 | } | | 197 | } |
196 | | | 198 | |
197 | return NULL; | | 199 | return NULL; |
198 | | | 200 | |
199 | win: | | 201 | win: |
200 | return bus_space_vaddr(bst, map->bsh); | | 202 | map->lm_data.bus_space.bst = bst; |
| | | 203 | return bus_space_vaddr(bst, map->lm_data.bus_space.bsh); |
201 | } | | 204 | } |
202 | | | 205 | |
203 | void | | 206 | void |
204 | drm_iounmap(struct drm_device *dev, struct drm_local_map *map) | | 207 | drm_iounmap(struct drm_device *dev, struct drm_local_map *map) |
205 | { | | 208 | { |
206 | const bus_space_tag_t bst = dev->bst; | | 209 | const bus_space_tag_t bst = dev->bst; |
207 | struct drm_bus_map *const bm = map->bus_map; | | 210 | struct drm_bus_map *const bm = map->lm_data.bus_space.bus_map; |
208 | | | 211 | |
209 | /* | | 212 | /* |
210 | * bm may be null if we have committed the horrible deed of | | 213 | * bm may be null if we have committed the horrible deed of |
211 | * borrowing from agp_i810 or genfb. | | 214 | * borrowing from agp_i810 or genfb. |
212 | */ | | 215 | */ |
213 | if (bm != NULL) { | | 216 | if (bm != NULL) { |
214 | KASSERT(bm->bm_mapped > 0); | | 217 | KASSERT(bm->bm_mapped > 0); |
215 | if (--bm->bm_mapped) | | 218 | if (--bm->bm_mapped) |
216 | bus_space_unmap(bst, bm->bm_bsh, bm->bm_size); | | 219 | bus_space_unmap(bst, bm->bm_bsh, bm->bm_size); |
217 | } | | 220 | } |
218 | } | | 221 | } |
219 | | | 222 | |
220 | /* | | 223 | /* |
221 | * Allocate a drm dma handle, allocate memory fit for DMA, and map it. | | 224 | * Allocate a drm dma handle, allocate memory fit for DMA, and map it. |
222 | * | | 225 | * |
223 | * XXX This is called drm_pci_alloc for hysterical raisins; it is not | | 226 | * XXX This is called drm_pci_alloc for hysterical raisins; it is not |
224 | * specific to PCI. | | 227 | * specific to PCI. |
225 | * | | 228 | * |
226 | * XXX For now, we use non-blocking allocations because this is called | | 229 | * XXX For now, we use non-blocking allocations because this is called |
227 | * by ioctls with the drm global mutex held. | | 230 | * by ioctls with the drm global mutex held. |
228 | * | | 231 | * |
229 | * XXX Error information is lost because this returns NULL on failure, | | 232 | * XXX Error information is lost because this returns NULL on failure, |
230 | * not even an error embedded in a pointer. | | 233 | * not even an error embedded in a pointer. |
231 | */ | | 234 | */ |
232 | struct drm_dma_handle * | | 235 | struct drm_dma_handle * |
233 | drm_pci_alloc(struct drm_device *dev, size_t size, size_t align) | | 236 | drm_pci_alloc(struct drm_device *dev, size_t size, size_t align) |
234 | { | | 237 | { |
235 | int nsegs; | | 238 | int nsegs; |
236 | int error; | | 239 | int error; |
237 | | | 240 | |
238 | /* | | 241 | /* |
239 | * Allocate a drm_dma_handle record. | | 242 | * Allocate a drm_dma_handle record. |
240 | * | | 243 | * |
241 | * XXX Must use kzalloc because callers pass this to kfree, not | | 244 | * XXX Must use kzalloc because callers pass this to kfree, not |
242 | * necessarily to drm_pci_free. Whattakludge. | | 245 | * necessarily to drm_pci_free. Whattakludge. |
243 | */ | | 246 | */ |
244 | struct drm_dma_handle *const dmah = kzalloc(sizeof(*dmah), GFP_ATOMIC); | | 247 | struct drm_dma_handle *const dmah = kzalloc(sizeof(*dmah), GFP_ATOMIC); |
245 | if (dmah == NULL) { | | 248 | if (dmah == NULL) { |
246 | error = -ENOMEM; | | 249 | error = -ENOMEM; |
247 | goto out; | | 250 | goto out; |
248 | } | | 251 | } |
249 | dmah->dmah_tag = dev->dmat; | | 252 | dmah->dmah_tag = dev->dmat; |
250 | | | 253 | |
251 | /* | | 254 | /* |
252 | * Allocate the requested amount of DMA-safe memory. | | 255 | * Allocate the requested amount of DMA-safe memory. |
253 | */ | | 256 | */ |
254 | /* XXX errno NetBSD->Linux */ | | 257 | /* XXX errno NetBSD->Linux */ |
255 | error = -bus_dmamem_alloc(dmah->dmah_tag, size, align, 0, | | 258 | error = -bus_dmamem_alloc(dmah->dmah_tag, size, align, 0, |
256 | &dmah->dmah_seg, 1, &nsegs, BUS_DMA_NOWAIT); | | 259 | &dmah->dmah_seg, 1, &nsegs, BUS_DMA_NOWAIT); |
257 | if (error) | | 260 | if (error) |
258 | goto fail0; | | 261 | goto fail0; |
259 | KASSERT(nsegs == 1); | | 262 | KASSERT(nsegs == 1); |
260 | | | 263 | |
261 | /* | | 264 | /* |
262 | * XXX Old drm passed BUS_DMA_NOWAIT below but BUS_DMA_WAITOK | | 265 | * XXX Old drm passed BUS_DMA_NOWAIT below but BUS_DMA_WAITOK |
263 | * above. WTF? | | 266 | * above. WTF? |
264 | */ | | 267 | */ |
265 | | | 268 | |
266 | /* | | 269 | /* |
267 | * Map the DMA-safe memory into kernel virtual address space. | | 270 | * Map the DMA-safe memory into kernel virtual address space. |
268 | */ | | 271 | */ |
269 | /* XXX errno NetBSD->Linux */ | | 272 | /* XXX errno NetBSD->Linux */ |
270 | error = -bus_dmamem_map(dmah->dmah_tag, &dmah->dmah_seg, 1, size, | | 273 | error = -bus_dmamem_map(dmah->dmah_tag, &dmah->dmah_seg, 1, size, |
271 | &dmah->vaddr, | | 274 | &dmah->vaddr, |
272 | (BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_NOCACHE)); | | 275 | (BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_NOCACHE)); |
273 | if (error) | | 276 | if (error) |
274 | goto fail1; | | 277 | goto fail1; |
275 | dmah->size = size; | | 278 | dmah->size = size; |
276 | | | 279 | |
277 | /* | | 280 | /* |
278 | * Create a map for DMA transfers. | | 281 | * Create a map for DMA transfers. |
279 | */ | | 282 | */ |
280 | /* XXX errno NetBSD->Linux */ | | 283 | /* XXX errno NetBSD->Linux */ |
281 | error = -bus_dmamap_create(dmah->dmah_tag, size, 1, size, 0, | | 284 | error = -bus_dmamap_create(dmah->dmah_tag, size, 1, size, 0, |
282 | BUS_DMA_NOWAIT, &dmah->dmah_map); | | 285 | BUS_DMA_NOWAIT, &dmah->dmah_map); |
283 | if (error) | | 286 | if (error) |
284 | goto fail2; | | 287 | goto fail2; |
285 | | | 288 | |
286 | /* | | 289 | /* |
287 | * Load the kva buffer into the map for DMA transfers. | | 290 | * Load the kva buffer into the map for DMA transfers. |
288 | */ | | 291 | */ |
289 | /* XXX errno NetBSD->Linux */ | | 292 | /* XXX errno NetBSD->Linux */ |
290 | error = -bus_dmamap_load(dmah->dmah_tag, dmah->dmah_map, dmah->vaddr, | | 293 | error = -bus_dmamap_load(dmah->dmah_tag, dmah->dmah_map, dmah->vaddr, |
291 | size, NULL, (BUS_DMA_NOWAIT | BUS_DMA_NOCACHE)); | | 294 | size, NULL, (BUS_DMA_NOWAIT | BUS_DMA_NOCACHE)); |
292 | if (error) | | 295 | if (error) |
293 | goto fail3; | | 296 | goto fail3; |
294 | | | 297 | |
295 | /* Record the bus address for convenient reference. */ | | 298 | /* Record the bus address for convenient reference. */ |
296 | dmah->busaddr = dmah->dmah_map->dm_segs[0].ds_addr; | | 299 | dmah->busaddr = dmah->dmah_map->dm_segs[0].ds_addr; |
297 | | | 300 | |
298 | /* Zero the DMA buffer. XXX Yikes! Is this necessary? */ | | 301 | /* Zero the DMA buffer. XXX Yikes! Is this necessary? */ |
299 | memset(dmah->vaddr, 0, size); | | 302 | memset(dmah->vaddr, 0, size); |
300 | | | 303 | |
301 | /* Success! */ | | 304 | /* Success! */ |
302 | return dmah; | | 305 | return dmah; |
303 | | | 306 | |
304 | fail3: bus_dmamap_destroy(dmah->dmah_tag, dmah->dmah_map); | | 307 | fail3: bus_dmamap_destroy(dmah->dmah_tag, dmah->dmah_map); |
305 | fail2: bus_dmamem_unmap(dmah->dmah_tag, dmah->vaddr, dmah->size); | | 308 | fail2: bus_dmamem_unmap(dmah->dmah_tag, dmah->vaddr, dmah->size); |
306 | fail1: bus_dmamem_free(dmah->dmah_tag, &dmah->dmah_seg, 1); | | 309 | fail1: bus_dmamem_free(dmah->dmah_tag, &dmah->dmah_seg, 1); |
307 | fail0: dmah->dmah_tag = NULL; /* XXX paranoia */ | | 310 | fail0: dmah->dmah_tag = NULL; /* XXX paranoia */ |
308 | kfree(dmah); | | 311 | kfree(dmah); |
309 | out: DRM_DEBUG("drm_pci_alloc failed: %d\n", error); | | 312 | out: DRM_DEBUG("drm_pci_alloc failed: %d\n", error); |
310 | return NULL; | | 313 | return NULL; |
311 | } | | 314 | } |
312 | | | 315 | |
313 | /* | | 316 | /* |
314 | * Release the bus DMA mappings and memory in dmah. | | 317 | * Release the bus DMA mappings and memory in dmah. |
315 | */ | | 318 | */ |
316 | void | | 319 | void |
317 | __drm_pci_free(struct drm_device *dev, struct drm_dma_handle *dmah) | | 320 | __drm_pci_free(struct drm_device *dev, struct drm_dma_handle *dmah) |
318 | { | | 321 | { |
319 | | | 322 | |
320 | bus_dmamap_unload(dmah->dmah_tag, dmah->dmah_map); | | 323 | bus_dmamap_unload(dmah->dmah_tag, dmah->dmah_map); |
321 | bus_dmamap_destroy(dmah->dmah_tag, dmah->dmah_map); | | 324 | bus_dmamap_destroy(dmah->dmah_tag, dmah->dmah_map); |
322 | bus_dmamem_unmap(dmah->dmah_tag, dmah->vaddr, dmah->size); | | 325 | bus_dmamem_unmap(dmah->dmah_tag, dmah->vaddr, dmah->size); |
323 | bus_dmamem_free(dmah->dmah_tag, &dmah->dmah_seg, 1); | | 326 | bus_dmamem_free(dmah->dmah_tag, &dmah->dmah_seg, 1); |
324 | dmah->dmah_tag = NULL; /* XXX paranoia */ | | 327 | dmah->dmah_tag = NULL; /* XXX paranoia */ |
325 | } | | 328 | } |
326 | | | 329 | |
327 | /* | | 330 | /* |
328 | * Release the bus DMA mappings and memory in dmah, and deallocate it. | | 331 | * Release the bus DMA mappings and memory in dmah, and deallocate it. |
329 | */ | | 332 | */ |
330 | void | | 333 | void |
331 | drm_pci_free(struct drm_device *dev, struct drm_dma_handle *dmah) | | 334 | drm_pci_free(struct drm_device *dev, struct drm_dma_handle *dmah) |
332 | { | | 335 | { |
333 | | | 336 | |
334 | __drm_pci_free(dev, dmah); | | 337 | __drm_pci_free(dev, dmah); |
335 | kfree(dmah); | | 338 | kfree(dmah); |
336 | } | | 339 | } |