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
= nvif_client(object
);
35 struct nvif_ioctl_v0 v0
;
38 if (size
>= sizeof(*args
) && args
->v0
.version
== 0) {
39 args
->v0
.owner
= NVIF_IOCTL_V0_OWNER_ANY
;
41 while (args
->v0
.path_nr
< ARRAY_SIZE(args
->v0
.path
)) {
42 args
->v0
.path
[args
->v0
.path_nr
++] = object
->handle
;
43 if (object
->parent
== object
)
45 object
= object
->parent
;
50 return client
->driver
->ioctl(client
->base
.priv
, client
->super
, data
, size
, hack
);
54 nvif_object_sclass(struct nvif_object
*object
, u32
*oclass
, int count
)
57 struct nvif_ioctl_v0 ioctl
;
58 struct nvif_ioctl_sclass_v0 sclass
;
60 u32 size
= count
* sizeof(args
->sclass
.oclass
[0]);
63 if (!(args
= kmalloc(sizeof(*args
) + size
, GFP_KERNEL
)))
65 args
->ioctl
.version
= 0;
66 args
->ioctl
.type
= NVIF_IOCTL_V0_SCLASS
;
67 args
->sclass
.version
= 0;
68 args
->sclass
.count
= count
;
70 memcpy(args
->sclass
.oclass
, oclass
, size
);
71 ret
= nvif_object_ioctl(object
, args
, sizeof(*args
) + size
, NULL
);
72 ret
= ret
? ret
: args
->sclass
.count
;
73 memcpy(oclass
, args
->sclass
.oclass
, size
);
79 nvif_object_rd(struct nvif_object
*object
, int size
, u64 addr
)
82 struct nvif_ioctl_v0 ioctl
;
83 struct nvif_ioctl_rd_v0 rd
;
85 .ioctl
.type
= NVIF_IOCTL_V0_RD
,
89 int ret
= nvif_object_ioctl(object
, &args
, sizeof(args
), NULL
);
98 nvif_object_wr(struct nvif_object
*object
, int size
, u64 addr
, u32 data
)
101 struct nvif_ioctl_v0 ioctl
;
102 struct nvif_ioctl_wr_v0 wr
;
104 .ioctl
.type
= NVIF_IOCTL_V0_WR
,
109 int ret
= nvif_object_ioctl(object
, &args
, sizeof(args
), NULL
);
116 nvif_object_mthd(struct nvif_object
*object
, u32 mthd
, void *data
, u32 size
)
119 struct nvif_ioctl_v0 ioctl
;
120 struct nvif_ioctl_mthd_v0 mthd
;
125 if (sizeof(*args
) + size
> sizeof(stack
)) {
126 if (!(args
= kmalloc(sizeof(*args
) + size
, GFP_KERNEL
)))
129 args
= (void *)stack
;
131 args
->ioctl
.version
= 0;
132 args
->ioctl
.type
= NVIF_IOCTL_V0_MTHD
;
133 args
->mthd
.version
= 0;
134 args
->mthd
.method
= mthd
;
136 memcpy(args
->mthd
.data
, data
, size
);
137 ret
= nvif_object_ioctl(object
, args
, sizeof(*args
) + size
, NULL
);
138 memcpy(data
, args
->mthd
.data
, size
);
139 if (args
!= (void *)stack
)
145 nvif_object_unmap(struct nvif_object
*object
)
147 if (object
->map
.size
) {
148 struct nvif_client
*client
= nvif_client(object
);
150 struct nvif_ioctl_v0 ioctl
;
151 struct nvif_ioctl_unmap unmap
;
153 .ioctl
.type
= NVIF_IOCTL_V0_UNMAP
,
156 if (object
->map
.ptr
) {
157 client
->driver
->unmap(client
, object
->map
.ptr
,
159 object
->map
.ptr
= NULL
;
162 nvif_object_ioctl(object
, &args
, sizeof(args
), NULL
);
163 object
->map
.size
= 0;
168 nvif_object_map(struct nvif_object
*object
)
170 struct nvif_client
*client
= nvif_client(object
);
172 struct nvif_ioctl_v0 ioctl
;
173 struct nvif_ioctl_map_v0 map
;
175 .ioctl
.type
= NVIF_IOCTL_V0_MAP
,
177 int ret
= nvif_object_ioctl(object
, &args
, sizeof(args
), NULL
);
179 object
->map
.size
= args
.map
.length
;
180 object
->map
.ptr
= client
->driver
->map(client
, args
.map
.handle
,
182 if (ret
= -ENOMEM
, object
->map
.ptr
)
184 nvif_object_unmap(object
);
190 struct nvif_ioctl_v0 ioctl
;
191 struct nvif_ioctl_new_v0
new;
195 nvif_object_fini(struct nvif_object
*object
)
197 struct ctor
*ctor
= container_of(object
->data
, typeof(*ctor
), new.data
);
198 if (object
->parent
) {
200 struct nvif_ioctl_v0 ioctl
;
201 struct nvif_ioctl_del del
;
203 .ioctl
.type
= NVIF_IOCTL_V0_DEL
,
206 nvif_object_unmap(object
);
207 nvif_object_ioctl(object
, &args
, sizeof(args
), NULL
);
213 nvif_object_ref(NULL
, &object
->parent
);
218 nvif_object_init(struct nvif_object
*parent
, void (*dtor
)(struct nvif_object
*),
219 u32 handle
, u32 oclass
, void *data
, u32 size
,
220 struct nvif_object
*object
)
225 object
->parent
= NULL
;
226 object
->object
= object
;
227 nvif_object_ref(parent
, &object
->parent
);
228 kref_init(&object
->refcount
);
229 object
->handle
= handle
;
230 object
->oclass
= oclass
;
234 object
->map
.ptr
= NULL
;
235 object
->map
.size
= 0;
237 if (object
->parent
) {
238 if (!(ctor
= kmalloc(sizeof(*ctor
) + size
, GFP_KERNEL
))) {
239 nvif_object_fini(object
);
242 object
->data
= ctor
->new.data
;
244 memcpy(object
->data
, data
, size
);
246 ctor
->ioctl
.version
= 0;
247 ctor
->ioctl
.type
= NVIF_IOCTL_V0_NEW
;
248 ctor
->new.version
= 0;
249 ctor
->new.route
= NVIF_IOCTL_V0_ROUTE_NVIF
;
250 ctor
->new.token
= (unsigned long)(void *)object
;
251 ctor
->new.handle
= handle
;
252 ctor
->new.oclass
= oclass
;
254 ret
= nvif_object_ioctl(parent
, ctor
, sizeof(*ctor
) +
255 object
->size
, &object
->priv
);
259 nvif_object_fini(object
);
264 nvif_object_del(struct nvif_object
*object
)
266 nvif_object_fini(object
);
271 nvif_object_new(struct nvif_object
*parent
, u32 handle
, u32 oclass
,
272 void *data
, u32 size
, struct nvif_object
**pobject
)
274 struct nvif_object
*object
= kzalloc(sizeof(*object
), GFP_KERNEL
);
276 int ret
= nvif_object_init(parent
, nvif_object_del
, handle
,
277 oclass
, data
, size
, object
);
289 nvif_object_put(struct kref
*kref
)
291 struct nvif_object
*object
=
292 container_of(kref
, typeof(*object
), refcount
);
293 object
->dtor(object
);
297 nvif_object_ref(struct nvif_object
*object
, struct nvif_object
**pobject
)
300 kref_get(&object
->refcount
);
302 kref_put(&(*pobject
)->refcount
, nvif_object_put
);