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
= kzalloc(sizeof(**psclass
) * args
->sclass
.count
, 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(struct nvif_object
*object
)
171 if (object
->map
.size
) {
172 struct nvif_client
*client
= object
->client
;
174 struct nvif_ioctl_v0 ioctl
;
175 struct nvif_ioctl_unmap unmap
;
177 .ioctl
.type
= NVIF_IOCTL_V0_UNMAP
,
180 if (object
->map
.ptr
) {
181 client
->driver
->unmap(client
, object
->map
.ptr
,
183 object
->map
.ptr
= NULL
;
186 nvif_object_ioctl(object
, &args
, sizeof(args
), NULL
);
187 object
->map
.size
= 0;
192 nvif_object_map(struct nvif_object
*object
)
194 struct nvif_client
*client
= object
->client
;
196 struct nvif_ioctl_v0 ioctl
;
197 struct nvif_ioctl_map_v0 map
;
199 .ioctl
.type
= NVIF_IOCTL_V0_MAP
,
201 int ret
= nvif_object_ioctl(object
, &args
, sizeof(args
), NULL
);
203 object
->map
.size
= args
.map
.length
;
204 object
->map
.ptr
= client
->driver
->map(client
, args
.map
.handle
,
206 if (ret
= -ENOMEM
, object
->map
.ptr
)
208 nvif_object_unmap(object
);
214 nvif_object_fini(struct nvif_object
*object
)
217 struct nvif_ioctl_v0 ioctl
;
218 struct nvif_ioctl_del del
;
220 .ioctl
.type
= NVIF_IOCTL_V0_DEL
,
226 nvif_object_unmap(object
);
227 nvif_object_ioctl(object
, &args
, sizeof(args
), NULL
);
228 object
->client
= NULL
;
232 nvif_object_init(struct nvif_object
*parent
, u32 handle
, s32 oclass
,
233 void *data
, u32 size
, struct nvif_object
*object
)
236 struct nvif_ioctl_v0 ioctl
;
237 struct nvif_ioctl_new_v0
new;
241 object
->client
= NULL
;
242 object
->handle
= handle
;
243 object
->oclass
= oclass
;
244 object
->map
.ptr
= NULL
;
245 object
->map
.size
= 0;
248 if (!(args
= kmalloc(sizeof(*args
) + size
, GFP_KERNEL
))) {
249 nvif_object_fini(object
);
253 args
->ioctl
.version
= 0;
254 args
->ioctl
.type
= NVIF_IOCTL_V0_NEW
;
255 args
->new.version
= 0;
256 args
->new.route
= parent
->client
->route
;
257 args
->new.token
= nvif_handle(object
);
258 args
->new.object
= nvif_handle(object
);
259 args
->new.handle
= handle
;
260 args
->new.oclass
= oclass
;
262 memcpy(args
->new.data
, data
, size
);
263 ret
= nvif_object_ioctl(parent
, args
, sizeof(*args
) + size
,
265 memcpy(data
, args
->new.data
, size
);
268 object
->client
= parent
->client
;
272 nvif_object_fini(object
);