Wed Jul 24 03:27:52 2013 UTC ()
Use kmem for drm_sg_mem records in local drm_scatter.c.


(riastradh)
diff -r1.1.2.1 -r1.1.2.2 src/sys/external/bsd/drm2/drm/drm_scatter.c

cvs diff -r1.1.2.1 -r1.1.2.2 src/sys/external/bsd/drm2/drm/drm_scatter.c (switch to unified diff)

--- src/sys/external/bsd/drm2/drm/drm_scatter.c 2013/07/24 02:46:33 1.1.2.1
+++ src/sys/external/bsd/drm2/drm/drm_scatter.c 2013/07/24 03:27:52 1.1.2.2
@@ -1,219 +1,220 @@ @@ -1,219 +1,220 @@
1/* $NetBSD: drm_scatter.c,v 1.1.2.1 2013/07/24 02:46:33 riastradh Exp $ */ 1/* $NetBSD: drm_scatter.c,v 1.1.2.2 2013/07/24 03:27:52 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_scatter.c,v 1.1.2.1 2013/07/24 02:46:33 riastradh Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: drm_scatter.c,v 1.1.2.2 2013/07/24 03:27:52 riastradh Exp $");
34 34
35#include <sys/types.h> 35#include <sys/types.h>
36#include <sys/bus.h> 36#include <sys/bus.h>
37#include <sys/errno.h> 37#include <sys/errno.h>
38#include <sys/systm.h> 38#include <sys/systm.h>
39 39
40#include <linux/slab.h> 40#include <linux/slab.h>
41 41
42#include <drm/drmP.h> 42#include <drm/drmP.h>
43 43
44static int drm_sg_alloc_mem(struct drm_device *, size_t, 44static int drm_sg_alloc_mem(struct drm_device *, size_t,
45 struct drm_sg_mem **); 45 struct drm_sg_mem **);
46 46
47int 47int
48drm_sg_alloc_ioctl(struct drm_device *dev, void *data, 48drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
49 struct drm_file *file __unused) 49 struct drm_file *file __unused)
50{ 50{
51 struct drm_scatter_gather *const request = data; 51 struct drm_scatter_gather *const request = data;
52 struct drm_sg_mem *sg; 52 struct drm_sg_mem *sg;
53 int error; 53 int error;
54 54
55 /* 55 /*
56 * XXX Should not hold this mutex during drm_sg_alloc. For 56 * XXX Should not hold this mutex during drm_sg_alloc. For
57 * now, we'll just use non-blocking allocations. 57 * now, we'll just use non-blocking allocations.
58 */ 58 */
59 KASSERT(mutex_is_locked(&drm_global_mutex)); 59 KASSERT(mutex_is_locked(&drm_global_mutex));
60 60
61 /* 61 /*
62 * Sanity-check the inputs. 62 * Sanity-check the inputs.
63 */ 63 */
64 if (!drm_core_check_feature(dev, DRIVER_SG)) 64 if (!drm_core_check_feature(dev, DRIVER_SG))
65 return -ENODEV; 65 return -ENODEV;
66 if (dev->sg != NULL) 66 if (dev->sg != NULL)
67 return -EBUSY; 67 return -EBUSY;
68 if (request->size > 0xffffffffUL) 68 if (request->size > 0xffffffffUL)
69 return -ENOMEM; 69 return -ENOMEM;
70 70
71 /* 71 /*
72 * Do the allocation. 72 * Do the allocation.
73 * 73 *
74 * XXX Would it be safe to drop drm_global_mutex here to avoid 74 * XXX Would it be safe to drop drm_global_mutex here to avoid
75 * holding it during allocation? 75 * holding it during allocation?
76 */ 76 */
77 error = drm_sg_alloc_mem(dev, request->size, &sg); 77 error = drm_sg_alloc_mem(dev, request->size, &sg);
78 if (error) 78 if (error)
79 return error; 79 return error;
80 80
81 /* Set it up to be the device's scatter-gather memory. */ 81 /* Set it up to be the device's scatter-gather memory. */
82 dev->sg = sg; 82 dev->sg = sg;
83 83
84 /* Success! */ 84 /* Success! */
85 request->handle = sg->handle; 85 request->handle = sg->handle;
86 return 0; 86 return 0;
87} 87}
88 88
89int 89int
90drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file) 90drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file)
91{ 91{
92 struct drm_scatter_gather *const request = data; 92 struct drm_scatter_gather *const request = data;
93 struct drm_sg_mem *sg; 93 struct drm_sg_mem *sg;
94 94
95 KASSERT(mutex_is_locked(&drm_global_mutex)); 95 KASSERT(mutex_is_locked(&drm_global_mutex));
96 96
97 /* 97 /*
98 * Sanity-check the inputs. 98 * Sanity-check the inputs.
99 */ 99 */
100 if (!drm_core_check_feature(dev, DRIVER_SG)) 100 if (!drm_core_check_feature(dev, DRIVER_SG))
101 return -ENODEV; 101 return -ENODEV;
102 102
103 sg = dev->sg; 103 sg = dev->sg;
104 if (sg == NULL) 104 if (sg == NULL)
105 return -ENXIO; 105 return -ENXIO;
106 if (sg->handle != request->handle) 106 if (sg->handle != request->handle)
107 return -EINVAL; 107 return -EINVAL;
108 108
109 /* Remove dev->sg. */ 109 /* Remove dev->sg. */
110 dev->sg = NULL; 110 dev->sg = NULL;
111 111
112 /* Success! */ 112 /* Success! */
113 drm_sg_cleanup(sg); 113 drm_sg_cleanup(sg);
114 return 0; 114 return 0;
115} 115}
116 116
117static int 117static int
118drm_sg_alloc_mem(struct drm_device *dev, size_t size, struct drm_sg_mem **sgp) 118drm_sg_alloc_mem(struct drm_device *dev, size_t size, struct drm_sg_mem **sgp)
119{ 119{
120 int nsegs; 120 int nsegs;
121 int error; 121 int error;
122 122
123 KASSERT(drm_core_check_feature(dev, DRIVER_SG)); 123 KASSERT(drm_core_check_feature(dev, DRIVER_SG));
124 124
125 KASSERT(size <= (size_t)0xffffffffUL); /* XXX 32-bit sizes only? */ 125 KASSERT(size <= (size_t)0xffffffffUL); /* XXX 32-bit sizes only? */
126 const size_t nbytes = round_page(size); 126 const size_t nbytes = round_page(size);
127 const size_t npages = nbytes >> PAGE_SHIFT; 127 const size_t npages = nbytes >> PAGE_SHIFT;
128 KASSERT(npages <= (size_t)INT_MAX); 128 KASSERT(npages <= (size_t)INT_MAX);
129 129
130 /* 130 /*
131 * Allocate a drm_sg_mem record. 131 * Allocate a drm_sg_mem record.
132 */ 132 */
133 struct drm_sg_mem *const sg = 133 struct drm_sg_mem *const sg =
134 kzalloc(offsetof(struct drm_sg_mem, sg_segs[npages]), GFP_ATOMIC); 134 kmem_zalloc(offsetof(struct drm_sg_mem, sg_segs[npages]),
 135 KM_NOSLEEP);
135 if (sg == NULL) 136 if (sg == NULL)
136 return -ENOMEM; 137 return -ENOMEM;
137 sg->sg_tag = dev->dmat; 138 sg->sg_tag = dev->dmat;
138 sg->sg_nsegs_max = (unsigned int)npages; 139 sg->sg_nsegs_max = (unsigned int)npages;
139 140
140 /* 141 /*
141 * Allocate the requested amount of DMA-safe memory. 142 * Allocate the requested amount of DMA-safe memory.
142 */ 143 */
143 KASSERT(sg->sg_nsegs_max <= (unsigned int)INT_MAX); 144 KASSERT(sg->sg_nsegs_max <= (unsigned int)INT_MAX);
144 /* XXX errno NetBSD->Linux */ 145 /* XXX errno NetBSD->Linux */
145 error = -bus_dmamem_alloc(sg->sg_tag, nbytes, PAGE_SIZE, 0, 146 error = -bus_dmamem_alloc(sg->sg_tag, nbytes, PAGE_SIZE, 0,
146 sg->sg_segs, (int)sg->sg_nsegs_max, &nsegs, BUS_DMA_NOWAIT); 147 sg->sg_segs, (int)sg->sg_nsegs_max, &nsegs, BUS_DMA_NOWAIT);
147 if (error) 148 if (error)
148 goto fail0; 149 goto fail0;
149 KASSERT(0 <= nsegs); 150 KASSERT(0 <= nsegs);
150 sg->sg_nsegs = (unsigned int)nsegs; 151 sg->sg_nsegs = (unsigned int)nsegs;
151 152
152 /* 153 /*
153 * XXX Old drm passed DRM_BUS_NOWAIT below but BUS_DMA_WAITOK 154 * XXX Old drm passed DRM_BUS_NOWAIT below but BUS_DMA_WAITOK
154 * above. WTF? 155 * above. WTF?
155 */ 156 */
156 157
157 /* 158 /*
158 * Map the DMA-safe memory into kernel virtual address space. 159 * Map the DMA-safe memory into kernel virtual address space.
159 */ 160 */
160 /* XXX errno NetBSD->Linux */ 161 /* XXX errno NetBSD->Linux */
161 error = -bus_dmamem_map(sg->sg_tag, sg->sg_segs, nsegs, nbytes, 162 error = -bus_dmamem_map(sg->sg_tag, sg->sg_segs, nsegs, nbytes,
162 &sg->virtual, 163 &sg->virtual,
163 (BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_NOCACHE)); 164 (BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_NOCACHE));
164 if (error) 165 if (error)
165 goto fail1; 166 goto fail1;
166 sg->sg_size = nbytes; 167 sg->sg_size = nbytes;
167 168
168 /* 169 /*
169 * Create a map for DMA transfers. 170 * Create a map for DMA transfers.
170 */ 171 */
171 /* XXX errno NetBSD->Linux */ 172 /* XXX errno NetBSD->Linux */
172 error = -bus_dmamap_create(sg->sg_tag, nbytes, nsegs, nbytes, 0, 173 error = -bus_dmamap_create(sg->sg_tag, nbytes, nsegs, nbytes, 0,
173 BUS_DMA_NOWAIT, &sg->sg_map); 174 BUS_DMA_NOWAIT, &sg->sg_map);
174 if (error) 175 if (error)
175 goto fail2; 176 goto fail2;
176 177
177 /* 178 /*
178 * Load the kva buffer into the map for DMA transfers. 179 * Load the kva buffer into the map for DMA transfers.
179 */ 180 */
180 /* XXX errno NetBSD->Linux */ 181 /* XXX errno NetBSD->Linux */
181 error = -bus_dmamap_load(sg->sg_tag, sg->sg_map, sg->virtual, nbytes, 182 error = -bus_dmamap_load(sg->sg_tag, sg->sg_map, sg->virtual, nbytes,
182 NULL, (BUS_DMA_NOWAIT | BUS_DMA_NOCACHE)); 183 NULL, (BUS_DMA_NOWAIT | BUS_DMA_NOCACHE));
183 if (error) 184 if (error)
184 goto fail3; 185 goto fail3;
185 186
186 /* 187 /*
187 * Use the kernel virtual address as the userland handle. 188 * Use the kernel virtual address as the userland handle.
188 * 189 *
189 * XXX This leaks some information about kernel virtual 190 * XXX This leaks some information about kernel virtual
190 * addresses to userland; should we use an idr instead? 191 * addresses to userland; should we use an idr instead?
191 */ 192 */
192 sg->handle = (unsigned long)(uintptr_t)sg->virtual; 193 sg->handle = (unsigned long)(uintptr_t)sg->virtual;
193 KASSERT(sg->virtual == (void *)(uintptr_t)sg->handle); 194 KASSERT(sg->virtual == (void *)(uintptr_t)sg->handle);
194 195
195 /* Success! */ 196 /* Success! */
196 *sgp = sg; 197 *sgp = sg;
197 return 0; 198 return 0;
198 199
199fail3: bus_dmamap_destroy(sg->sg_tag, sg->sg_map); 200fail3: bus_dmamap_destroy(sg->sg_tag, sg->sg_map);
200fail2: bus_dmamem_unmap(sg->sg_tag, sg->virtual, sg->sg_size); 201fail2: bus_dmamem_unmap(sg->sg_tag, sg->virtual, sg->sg_size);
201fail1: KASSERT(sg->sg_nsegs <= (unsigned int)INT_MAX); 202fail1: KASSERT(sg->sg_nsegs <= (unsigned int)INT_MAX);
202 bus_dmamem_free(sg->sg_tag, sg->sg_segs, (int)sg->sg_nsegs); 203 bus_dmamem_free(sg->sg_tag, sg->sg_segs, (int)sg->sg_nsegs);
203fail0: sg->sg_tag = NULL; /* XXX paranoia */ 204fail0: sg->sg_tag = NULL; /* XXX paranoia */
204 kfree(sg); 205 kfree(sg);
205 return error; 206 return error;
206} 207}
207 208
208void 209void
209drm_sg_cleanup(struct drm_sg_mem *sg) 210drm_sg_cleanup(struct drm_sg_mem *sg)
210{ 211{
211 212
212 bus_dmamap_unload(sg->sg_tag, sg->sg_map); 213 bus_dmamap_unload(sg->sg_tag, sg->sg_map);
213 bus_dmamap_destroy(sg->sg_tag, sg->sg_map); 214 bus_dmamap_destroy(sg->sg_tag, sg->sg_map);
214 bus_dmamem_unmap(sg->sg_tag, sg->virtual, sg->sg_size); 215 bus_dmamem_unmap(sg->sg_tag, sg->virtual, sg->sg_size);
215 KASSERT(sg->sg_nsegs <= (unsigned int)INT_MAX); 216 KASSERT(sg->sg_nsegs <= (unsigned int)INT_MAX);
216 bus_dmamem_free(sg->sg_tag, sg->sg_segs, (int)sg->sg_nsegs); 217 bus_dmamem_free(sg->sg_tag, sg->sg_segs, (int)sg->sg_nsegs);
217 sg->sg_tag = NULL; /* XXX paranoia */ 218 sg->sg_tag = NULL; /* XXX paranoia */
218 kfree(sg); 219 kmem_free(sg, offsetof(struct drm_sg_mem, sg_segs[sg->sg_nsegs_max]));
219} 220}