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>
34 struct nvkm_client_notify
{
35 struct nvkm_client
*client
;
40 struct nvif_notify_rep_v0 v0
;
45 nvkm_client_notify(struct nvkm_notify
*n
)
47 struct nvkm_client_notify
*notify
= container_of(n
, typeof(*notify
), n
);
48 struct nvkm_client
*client
= notify
->client
;
49 return client
->ntfy(¬ify
->rep
, notify
->size
, n
->data
, n
->size
);
53 nvkm_client_notify_put(struct nvkm_client
*client
, int index
)
55 if (index
< ARRAY_SIZE(client
->notify
)) {
56 if (client
->notify
[index
]) {
57 nvkm_notify_put(&client
->notify
[index
]->n
);
65 nvkm_client_notify_get(struct nvkm_client
*client
, int index
)
67 if (index
< ARRAY_SIZE(client
->notify
)) {
68 if (client
->notify
[index
]) {
69 nvkm_notify_get(&client
->notify
[index
]->n
);
77 nvkm_client_notify_del(struct nvkm_client
*client
, int index
)
79 if (index
< ARRAY_SIZE(client
->notify
)) {
80 if (client
->notify
[index
]) {
81 nvkm_notify_fini(&client
->notify
[index
]->n
);
82 kfree(client
->notify
[index
]);
83 client
->notify
[index
] = NULL
;
91 nvkm_client_notify_new(struct nvkm_object
*object
,
92 struct nvkm_event
*event
, void *data
, u32 size
)
94 struct nvkm_client
*client
= object
->client
;
95 struct nvkm_client_notify
*notify
;
97 struct nvif_notify_req_v0 v0
;
102 for (index
= 0; index
< ARRAY_SIZE(client
->notify
); index
++) {
103 if (!client
->notify
[index
])
107 if (index
== ARRAY_SIZE(client
->notify
))
110 notify
= kzalloc(sizeof(*notify
), GFP_KERNEL
);
114 nvif_ioctl(object
, "notify new size %d\n", size
);
115 if (!(ret
= nvif_unpack(ret
, &data
, &size
, req
->v0
, 0, 0, true))) {
116 nvif_ioctl(object
, "notify new vers %d reply %d route %02x "
117 "token %llx\n", req
->v0
.version
,
118 req
->v0
.reply
, req
->v0
.route
, req
->v0
.token
);
119 notify
->version
= req
->v0
.version
;
120 notify
->size
= sizeof(notify
->rep
.v0
);
121 notify
->rep
.v0
.version
= req
->v0
.version
;
122 notify
->rep
.v0
.route
= req
->v0
.route
;
123 notify
->rep
.v0
.token
= req
->v0
.token
;
124 reply
= req
->v0
.reply
;
128 ret
= nvkm_notify_init(object
, event
, nvkm_client_notify
,
129 false, data
, size
, reply
, ¬ify
->n
);
131 client
->notify
[index
] = notify
;
132 notify
->client
= client
;
142 nvkm_client_mthd_devlist(struct nvkm_object
*object
, void *data
, u32 size
)
145 struct nv_client_devlist_v0 v0
;
149 nvif_ioctl(object
, "client devlist size %d\n", size
);
150 if (!(ret
= nvif_unpack(ret
, &data
, &size
, args
->v0
, 0, 0, true))) {
151 nvif_ioctl(object
, "client devlist vers %d count %d\n",
152 args
->v0
.version
, args
->v0
.count
);
153 if (size
== sizeof(args
->v0
.device
[0]) * args
->v0
.count
) {
154 ret
= nvkm_device_list(args
->v0
.device
, args
->v0
.count
);
156 args
->v0
.count
= ret
;
168 nvkm_client_mthd(struct nvkm_object
*object
, u32 mthd
, void *data
, u32 size
)
171 case NV_CLIENT_DEVLIST
:
172 return nvkm_client_mthd_devlist(object
, data
, size
);
180 nvkm_client_child_new(const struct nvkm_oclass
*oclass
,
181 void *data
, u32 size
, struct nvkm_object
**pobject
)
183 return oclass
->base
.ctor(oclass
, data
, size
, pobject
);
187 nvkm_client_child_get(struct nvkm_object
*object
, int index
,
188 struct nvkm_oclass
*oclass
)
190 const struct nvkm_sclass
*sclass
;
193 case 0: sclass
= &nvkm_udevice_sclass
; break;
198 oclass
->ctor
= nvkm_client_child_new
;
199 oclass
->base
= *sclass
;
203 static const struct nvkm_object_func
204 nvkm_client_object_func
= {
205 .mthd
= nvkm_client_mthd
,
206 .sclass
= nvkm_client_child_get
,
210 nvkm_client_remove(struct nvkm_client
*client
, struct nvkm_object
*object
)
212 if (!RB_EMPTY_NODE(&object
->node
))
213 rb_erase(&object
->node
, &client
->objroot
);
217 nvkm_client_insert(struct nvkm_client
*client
, struct nvkm_object
*object
)
219 struct rb_node
**ptr
= &client
->objroot
.rb_node
;
220 struct rb_node
*parent
= NULL
;
223 struct nvkm_object
*this =
224 container_of(*ptr
, typeof(*this), node
);
226 if (object
->object
< this->object
)
227 ptr
= &parent
->rb_left
;
229 if (object
->object
> this->object
)
230 ptr
= &parent
->rb_right
;
235 rb_link_node(&object
->node
, parent
, ptr
);
236 rb_insert_color(&object
->node
, &client
->objroot
);
241 nvkm_client_search(struct nvkm_client
*client
, u64 handle
)
243 struct rb_node
*node
= client
->objroot
.rb_node
;
245 struct nvkm_object
*object
=
246 container_of(node
, typeof(*object
), node
);
247 if (handle
< object
->object
)
248 node
= node
->rb_left
;
250 if (handle
> object
->object
)
251 node
= node
->rb_right
;
259 nvkm_client_fini(struct nvkm_client
*client
, bool suspend
)
261 struct nvkm_object
*object
= &client
->object
;
262 const char *name
[2] = { "fini", "suspend" };
264 nvif_debug(object
, "%s notify\n", name
[suspend
]);
265 for (i
= 0; i
< ARRAY_SIZE(client
->notify
); i
++)
266 nvkm_client_notify_put(client
, i
);
267 return nvkm_object_fini(&client
->object
, suspend
);
271 nvkm_client_init(struct nvkm_client
*client
)
273 return nvkm_object_init(&client
->object
);
277 nvkm_client_del(struct nvkm_client
**pclient
)
279 struct nvkm_client
*client
= *pclient
;
282 nvkm_client_fini(client
, false);
283 for (i
= 0; i
< ARRAY_SIZE(client
->notify
); i
++)
284 nvkm_client_notify_del(client
, i
);
285 nvkm_object_dtor(&client
->object
);
292 nvkm_client_new(const char *name
, u64 device
, const char *cfg
,
293 const char *dbg
, struct nvkm_client
**pclient
)
295 struct nvkm_oclass oclass
= {};
296 struct nvkm_client
*client
;
298 if (!(client
= *pclient
= kzalloc(sizeof(*client
), GFP_KERNEL
)))
300 oclass
.client
= client
;
302 nvkm_object_ctor(&nvkm_client_object_func
, &oclass
, &client
->object
);
303 snprintf(client
->name
, sizeof(client
->name
), "%s", name
);
304 client
->device
= device
;
305 client
->debug
= nvkm_dbgopt(dbg
, "CLIENT");
306 client
->objroot
= RB_ROOT
;
307 client
->dmaroot
= RB_ROOT
;