2 * Copyright 2014 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 * Authors: Ben Skeggs <bskeggs@redhat.com>
25 #include <nvif/object.h>
26 #include <nvif/client.h>
27 #include <nvif/driver.h>
28 #include <nvif/ioctl.h>
31 nvif_object_ioctl(struct nvif_object
*object
, void *data
, u32 size
, void **hack
)
33 struct nvif_client
*client
= object
->client
;
35 struct nvif_ioctl_v0 v0
;
38 if (size
>= sizeof(*args
) && args
->v0
.version
== 0) {
39 if (object
!= &client
->object
)
40 args
->v0
.object
= nvif_handle(object
);
43 args
->v0
.owner
= NVIF_IOCTL_V0_OWNER_ANY
;
47 return client
->driver
->ioctl(client
->object
.priv
, client
->super
,
52 nvif_object_sclass_put(struct nvif_sclass
**psclass
)
59 nvif_object_sclass_get(struct nvif_object
*object
, struct nvif_sclass
**psclass
)
62 struct nvif_ioctl_v0 ioctl
;
63 struct nvif_ioctl_sclass_v0 sclass
;
69 size
= sizeof(*args
) + cnt
* sizeof(args
->sclass
.oclass
[0]);
70 if (!(args
= kmalloc(size
, GFP_KERNEL
)))
72 args
->ioctl
.version
= 0;
73 args
->ioctl
.type
= NVIF_IOCTL_V0_SCLASS
;
74 args
->sclass
.version
= 0;
75 args
->sclass
.count
= cnt
;
77 ret
= nvif_object_ioctl(object
, args
, size
, NULL
);
78 if (ret
== 0 && args
->sclass
.count
<= cnt
)
80 cnt
= args
->sclass
.count
;
86 *psclass
= kcalloc(args
->sclass
.count
, sizeof(**psclass
), GFP_KERNEL
);
88 for (i
= 0; i
< args
->sclass
.count
; i
++) {
89 (*psclass
)[i
].oclass
= args
->sclass
.oclass
[i
].oclass
;
90 (*psclass
)[i
].minver
= args
->sclass
.oclass
[i
].minver
;
91 (*psclass
)[i
].maxver
= args
->sclass
.oclass
[i
].maxver
;
93 ret
= args
->sclass
.count
;
103 nvif_object_rd(struct nvif_object
*object
, int size
, u64 addr
)
106 struct nvif_ioctl_v0 ioctl
;
107 struct nvif_ioctl_rd_v0 rd
;
109 .ioctl
.type
= NVIF_IOCTL_V0_RD
,
113 int ret
= nvif_object_ioctl(object
, &args
, sizeof(args
), NULL
);
122 nvif_object_wr(struct nvif_object
*object
, int size
, u64 addr
, u32 data
)
125 struct nvif_ioctl_v0 ioctl
;
126 struct nvif_ioctl_wr_v0 wr
;
128 .ioctl
.type
= NVIF_IOCTL_V0_WR
,
133 int ret
= nvif_object_ioctl(object
, &args
, sizeof(args
), NULL
);
140 nvif_object_mthd(struct nvif_object
*object
, u32 mthd
, void *data
, u32 size
)
143 struct nvif_ioctl_v0 ioctl
;
144 struct nvif_ioctl_mthd_v0 mthd
;
149 if (sizeof(*args
) + size
> sizeof(stack
)) {
150 if (!(args
= kmalloc(sizeof(*args
) + size
, GFP_KERNEL
)))
153 args
= (void *)stack
;
155 args
->ioctl
.version
= 0;
156 args
->ioctl
.type
= NVIF_IOCTL_V0_MTHD
;
157 args
->mthd
.version
= 0;
158 args
->mthd
.method
= mthd
;
160 memcpy(args
->mthd
.data
, data
, size
);
161 ret
= nvif_object_ioctl(object
, args
, sizeof(*args
) + size
, NULL
);
162 memcpy(data
, args
->mthd
.data
, size
);
163 if (args
!= (void *)stack
)
169 nvif_object_unmap_handle(struct nvif_object
*object
)
172 struct nvif_ioctl_v0 ioctl
;
173 struct nvif_ioctl_unmap unmap
;
175 .ioctl
.type
= NVIF_IOCTL_V0_UNMAP
,
178 nvif_object_ioctl(object
, &args
, sizeof(args
), NULL
);
182 nvif_object_map_handle(struct nvif_object
*object
, void *argv
, u32 argc
,
183 u64
*handle
, u64
*length
)
186 struct nvif_ioctl_v0 ioctl
;
187 struct nvif_ioctl_map_v0 map
;
189 u32 argn
= sizeof(*args
) + argc
;
192 if (!(args
= kzalloc(argn
, GFP_KERNEL
)))
194 args
->ioctl
.type
= NVIF_IOCTL_V0_MAP
;
195 memcpy(args
->map
.data
, argv
, argc
);
197 ret
= nvif_object_ioctl(object
, args
, argn
, NULL
);
198 *handle
= args
->map
.handle
;
199 *length
= args
->map
.length
;
200 maptype
= args
->map
.type
;
202 return ret
? ret
: (maptype
== NVIF_IOCTL_MAP_V0_IO
);
206 nvif_object_unmap(struct nvif_object
*object
)
208 struct nvif_client
*client
= object
->client
;
209 if (object
->map
.ptr
) {
210 if (object
->map
.size
) {
211 client
->driver
->unmap(client
, object
->map
.ptr
,
213 object
->map
.size
= 0;
215 object
->map
.ptr
= NULL
;
216 nvif_object_unmap_handle(object
);
221 nvif_object_map(struct nvif_object
*object
, void *argv
, u32 argc
)
223 struct nvif_client
*client
= object
->client
;
225 int ret
= nvif_object_map_handle(object
, argv
, argc
, &handle
, &length
);
228 object
->map
.ptr
= client
->driver
->map(client
,
231 if (ret
= -ENOMEM
, object
->map
.ptr
) {
232 object
->map
.size
= length
;
236 object
->map
.ptr
= (void *)(unsigned long)handle
;
239 nvif_object_unmap_handle(object
);
245 nvif_object_fini(struct nvif_object
*object
)
248 struct nvif_ioctl_v0 ioctl
;
249 struct nvif_ioctl_del del
;
251 .ioctl
.type
= NVIF_IOCTL_V0_DEL
,
257 nvif_object_unmap(object
);
258 nvif_object_ioctl(object
, &args
, sizeof(args
), NULL
);
259 object
->client
= NULL
;
263 nvif_object_init(struct nvif_object
*parent
, u32 handle
, s32 oclass
,
264 void *data
, u32 size
, struct nvif_object
*object
)
267 struct nvif_ioctl_v0 ioctl
;
268 struct nvif_ioctl_new_v0
new;
272 object
->client
= NULL
;
273 object
->handle
= handle
;
274 object
->oclass
= oclass
;
275 object
->map
.ptr
= NULL
;
276 object
->map
.size
= 0;
279 if (!(args
= kmalloc(sizeof(*args
) + size
, GFP_KERNEL
))) {
280 nvif_object_fini(object
);
284 args
->ioctl
.version
= 0;
285 args
->ioctl
.type
= NVIF_IOCTL_V0_NEW
;
286 args
->new.version
= 0;
287 args
->new.route
= parent
->client
->route
;
288 args
->new.token
= nvif_handle(object
);
289 args
->new.object
= nvif_handle(object
);
290 args
->new.handle
= handle
;
291 args
->new.oclass
= oclass
;
293 memcpy(args
->new.data
, data
, size
);
294 ret
= nvif_object_ioctl(parent
, args
, sizeof(*args
) + size
,
296 memcpy(data
, args
->new.data
, size
);
299 object
->client
= parent
->client
;
303 nvif_object_fini(object
);