2 * Copyright 2012 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.
24 #include <core/client.h>
25 #include <core/device.h>
26 #include <core/notify.h>
27 #include <core/option.h>
29 #include <nvif/class.h>
30 #include <nvif/event.h>
31 #include <nvif/if0000.h>
32 #include <nvif/unpack.h>
35 nvkm_uclient_new(const struct nvkm_oclass
*oclass
, void *argv
, u32 argc
,
36 struct nvkm_object
**pobject
)
39 struct nvif_client_v0 v0
;
41 struct nvkm_client
*client
;
44 if (!(ret
= nvif_unpack(ret
, &argv
, &argc
, args
->v0
, 0, 0, false))){
45 args
->v0
.name
[sizeof(args
->v0
.name
) - 1] = 0;
46 ret
= nvkm_client_new(args
->v0
.name
, args
->v0
.device
, NULL
,
47 NULL
, oclass
->client
->ntfy
, &client
);
53 client
->object
.client
= oclass
->client
;
54 client
->object
.handle
= oclass
->handle
;
55 client
->object
.route
= oclass
->route
;
56 client
->object
.token
= oclass
->token
;
57 client
->object
.object
= oclass
->object
;
58 client
->debug
= oclass
->client
->debug
;
59 *pobject
= &client
->object
;
63 const struct nvkm_sclass
64 nvkm_uclient_sclass
= {
65 .oclass
= NVIF_CLASS_CLIENT
,
68 .ctor
= nvkm_uclient_new
,
71 struct nvkm_client_notify
{
72 struct nvkm_client
*client
;
77 struct nvif_notify_rep_v0 v0
;
82 nvkm_client_notify(struct nvkm_notify
*n
)
84 struct nvkm_client_notify
*notify
= container_of(n
, typeof(*notify
), n
);
85 struct nvkm_client
*client
= notify
->client
;
86 return client
->ntfy(¬ify
->rep
, notify
->size
, n
->data
, n
->size
);
90 nvkm_client_notify_put(struct nvkm_client
*client
, int index
)
92 if (index
< ARRAY_SIZE(client
->notify
)) {
93 if (client
->notify
[index
]) {
94 nvkm_notify_put(&client
->notify
[index
]->n
);
102 nvkm_client_notify_get(struct nvkm_client
*client
, int index
)
104 if (index
< ARRAY_SIZE(client
->notify
)) {
105 if (client
->notify
[index
]) {
106 nvkm_notify_get(&client
->notify
[index
]->n
);
114 nvkm_client_notify_del(struct nvkm_client
*client
, int index
)
116 if (index
< ARRAY_SIZE(client
->notify
)) {
117 if (client
->notify
[index
]) {
118 nvkm_notify_fini(&client
->notify
[index
]->n
);
119 kfree(client
->notify
[index
]);
120 client
->notify
[index
] = NULL
;
128 nvkm_client_notify_new(struct nvkm_object
*object
,
129 struct nvkm_event
*event
, void *data
, u32 size
)
131 struct nvkm_client
*client
= object
->client
;
132 struct nvkm_client_notify
*notify
;
134 struct nvif_notify_req_v0 v0
;
139 for (index
= 0; index
< ARRAY_SIZE(client
->notify
); index
++) {
140 if (!client
->notify
[index
])
144 if (index
== ARRAY_SIZE(client
->notify
))
147 notify
= kzalloc(sizeof(*notify
), GFP_KERNEL
);
151 nvif_ioctl(object
, "notify new size %d\n", size
);
152 if (!(ret
= nvif_unpack(ret
, &data
, &size
, req
->v0
, 0, 0, true))) {
153 nvif_ioctl(object
, "notify new vers %d reply %d route %02x "
154 "token %llx\n", req
->v0
.version
,
155 req
->v0
.reply
, req
->v0
.route
, req
->v0
.token
);
156 notify
->version
= req
->v0
.version
;
157 notify
->size
= sizeof(notify
->rep
.v0
);
158 notify
->rep
.v0
.version
= req
->v0
.version
;
159 notify
->rep
.v0
.route
= req
->v0
.route
;
160 notify
->rep
.v0
.token
= req
->v0
.token
;
161 reply
= req
->v0
.reply
;
165 ret
= nvkm_notify_init(object
, event
, nvkm_client_notify
,
166 false, data
, size
, reply
, ¬ify
->n
);
168 client
->notify
[index
] = notify
;
169 notify
->client
= client
;
178 static const struct nvkm_object_func nvkm_client
;
180 nvkm_client_search(struct nvkm_client
*client
, u64 handle
)
182 struct nvkm_object
*object
;
184 object
= nvkm_object_search(client
, handle
, &nvkm_client
);
186 return (void *)object
;
188 return nvkm_client(object
);
192 nvkm_client_mthd_devlist(struct nvkm_client
*client
, void *data
, u32 size
)
195 struct nvif_client_devlist_v0 v0
;
199 nvif_ioctl(&client
->object
, "client devlist size %d\n", size
);
200 if (!(ret
= nvif_unpack(ret
, &data
, &size
, args
->v0
, 0, 0, true))) {
201 nvif_ioctl(&client
->object
, "client devlist vers %d count %d\n",
202 args
->v0
.version
, args
->v0
.count
);
203 if (size
== sizeof(args
->v0
.device
[0]) * args
->v0
.count
) {
204 ret
= nvkm_device_list(args
->v0
.device
, args
->v0
.count
);
206 args
->v0
.count
= ret
;
218 nvkm_client_mthd(struct nvkm_object
*object
, u32 mthd
, void *data
, u32 size
)
220 struct nvkm_client
*client
= nvkm_client(object
);
222 case NVIF_CLIENT_V0_DEVLIST
:
223 return nvkm_client_mthd_devlist(client
, data
, size
);
231 nvkm_client_child_new(const struct nvkm_oclass
*oclass
,
232 void *data
, u32 size
, struct nvkm_object
**pobject
)
234 return oclass
->base
.ctor(oclass
, data
, size
, pobject
);
238 nvkm_client_child_get(struct nvkm_object
*object
, int index
,
239 struct nvkm_oclass
*oclass
)
241 const struct nvkm_sclass
*sclass
;
244 case 0: sclass
= &nvkm_uclient_sclass
; break;
245 case 1: sclass
= &nvkm_udevice_sclass
; break;
250 oclass
->ctor
= nvkm_client_child_new
;
251 oclass
->base
= *sclass
;
256 nvkm_client_fini(struct nvkm_object
*object
, bool suspend
)
258 struct nvkm_client
*client
= nvkm_client(object
);
259 const char *name
[2] = { "fini", "suspend" };
261 nvif_debug(object
, "%s notify\n", name
[suspend
]);
262 for (i
= 0; i
< ARRAY_SIZE(client
->notify
); i
++)
263 nvkm_client_notify_put(client
, i
);
268 nvkm_client_dtor(struct nvkm_object
*object
)
270 struct nvkm_client
*client
= nvkm_client(object
);
272 for (i
= 0; i
< ARRAY_SIZE(client
->notify
); i
++)
273 nvkm_client_notify_del(client
, i
);
277 static const struct nvkm_object_func
279 .dtor
= nvkm_client_dtor
,
280 .fini
= nvkm_client_fini
,
281 .mthd
= nvkm_client_mthd
,
282 .sclass
= nvkm_client_child_get
,
286 nvkm_client_new(const char *name
, u64 device
, const char *cfg
,
288 int (*ntfy
)(const void *, u32
, const void *, u32
),
289 struct nvkm_client
**pclient
)
291 struct nvkm_oclass oclass
= { .base
= nvkm_uclient_sclass
};
292 struct nvkm_client
*client
;
294 if (!(client
= *pclient
= kzalloc(sizeof(*client
), GFP_KERNEL
)))
296 oclass
.client
= client
;
298 nvkm_object_ctor(&nvkm_client
, &oclass
, &client
->object
);
299 snprintf(client
->name
, sizeof(client
->name
), "%s", name
);
300 client
->device
= device
;
301 client
->debug
= nvkm_dbgopt(dbg
, "CLIENT");
302 client
->objroot
= RB_ROOT
;
304 INIT_LIST_HEAD(&client
->umem
);
305 spin_lock_init(&client
->lock
);