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/unpack.h>
33 struct nvkm_client_notify
{
34 struct nvkm_client
*client
;
39 struct nvif_notify_rep_v0 v0
;
44 nvkm_client_notify(struct nvkm_notify
*n
)
46 struct nvkm_client_notify
*notify
= container_of(n
, typeof(*notify
), n
);
47 struct nvkm_client
*client
= notify
->client
;
48 return client
->ntfy(¬ify
->rep
, notify
->size
, n
->data
, n
->size
);
52 nvkm_client_notify_put(struct nvkm_client
*client
, int index
)
54 if (index
< ARRAY_SIZE(client
->notify
)) {
55 if (client
->notify
[index
]) {
56 nvkm_notify_put(&client
->notify
[index
]->n
);
64 nvkm_client_notify_get(struct nvkm_client
*client
, int index
)
66 if (index
< ARRAY_SIZE(client
->notify
)) {
67 if (client
->notify
[index
]) {
68 nvkm_notify_get(&client
->notify
[index
]->n
);
76 nvkm_client_notify_del(struct nvkm_client
*client
, int index
)
78 if (index
< ARRAY_SIZE(client
->notify
)) {
79 if (client
->notify
[index
]) {
80 nvkm_notify_fini(&client
->notify
[index
]->n
);
81 kfree(client
->notify
[index
]);
82 client
->notify
[index
] = NULL
;
90 nvkm_client_notify_new(struct nvkm_object
*object
,
91 struct nvkm_event
*event
, void *data
, u32 size
)
93 struct nvkm_client
*client
= object
->client
;
94 struct nvkm_client_notify
*notify
;
96 struct nvif_notify_req_v0 v0
;
101 for (index
= 0; index
< ARRAY_SIZE(client
->notify
); index
++) {
102 if (!client
->notify
[index
])
106 if (index
== ARRAY_SIZE(client
->notify
))
109 notify
= kzalloc(sizeof(*notify
), GFP_KERNEL
);
113 nvif_ioctl(object
, "notify new size %d\n", size
);
114 if (nvif_unpack(req
->v0
, 0, 0, true)) {
115 nvif_ioctl(object
, "notify new vers %d reply %d route %02x "
116 "token %llx\n", req
->v0
.version
,
117 req
->v0
.reply
, req
->v0
.route
, req
->v0
.token
);
118 notify
->version
= req
->v0
.version
;
119 notify
->size
= sizeof(notify
->rep
.v0
);
120 notify
->rep
.v0
.version
= req
->v0
.version
;
121 notify
->rep
.v0
.route
= req
->v0
.route
;
122 notify
->rep
.v0
.token
= req
->v0
.token
;
123 reply
= req
->v0
.reply
;
127 ret
= nvkm_notify_init(object
, event
, nvkm_client_notify
,
128 false, data
, size
, reply
, ¬ify
->n
);
130 client
->notify
[index
] = notify
;
131 notify
->client
= client
;
141 nvkm_client_mthd_devlist(struct nvkm_object
*object
, void *data
, u32 size
)
144 struct nv_client_devlist_v0 v0
;
148 nvif_ioctl(object
, "client devlist size %d\n", size
);
149 if (nvif_unpack(args
->v0
, 0, 0, true)) {
150 nvif_ioctl(object
, "client devlist vers %d count %d\n",
151 args
->v0
.version
, args
->v0
.count
);
152 if (size
== sizeof(args
->v0
.device
[0]) * args
->v0
.count
) {
153 ret
= nvkm_device_list(args
->v0
.device
, args
->v0
.count
);
155 args
->v0
.count
= ret
;
167 nvkm_client_mthd(struct nvkm_object
*object
, u32 mthd
, void *data
, u32 size
)
170 case NV_CLIENT_DEVLIST
:
171 return nvkm_client_mthd_devlist(object
, data
, size
);
179 nvkm_client_child_new(const struct nvkm_oclass
*oclass
,
180 void *data
, u32 size
, struct nvkm_object
**pobject
)
182 return oclass
->base
.ctor(oclass
, data
, size
, pobject
);
186 nvkm_client_child_get(struct nvkm_object
*object
, int index
,
187 struct nvkm_oclass
*oclass
)
189 const struct nvkm_sclass
*sclass
;
192 case 0: sclass
= &nvkm_udevice_sclass
; break;
197 oclass
->ctor
= nvkm_client_child_new
;
198 oclass
->base
= *sclass
;
202 static const struct nvkm_object_func
203 nvkm_client_object_func
= {
204 .mthd
= nvkm_client_mthd
,
205 .sclass
= nvkm_client_child_get
,
209 nvkm_client_remove(struct nvkm_client
*client
, struct nvkm_object
*object
)
211 if (!RB_EMPTY_NODE(&object
->node
))
212 rb_erase(&object
->node
, &client
->objroot
);
216 nvkm_client_insert(struct nvkm_client
*client
, struct nvkm_object
*object
)
218 struct rb_node
**ptr
= &client
->objroot
.rb_node
;
219 struct rb_node
*parent
= NULL
;
222 struct nvkm_object
*this =
223 container_of(*ptr
, typeof(*this), node
);
225 if (object
->object
< this->object
)
226 ptr
= &parent
->rb_left
;
228 if (object
->object
> this->object
)
229 ptr
= &parent
->rb_right
;
234 rb_link_node(&object
->node
, parent
, ptr
);
235 rb_insert_color(&object
->node
, &client
->objroot
);
240 nvkm_client_search(struct nvkm_client
*client
, u64 handle
)
242 struct rb_node
*node
= client
->objroot
.rb_node
;
244 struct nvkm_object
*object
=
245 container_of(node
, typeof(*object
), node
);
246 if (handle
< object
->object
)
247 node
= node
->rb_left
;
249 if (handle
> object
->object
)
250 node
= node
->rb_right
;
258 nvkm_client_fini(struct nvkm_client
*client
, bool suspend
)
260 struct nvkm_object
*object
= &client
->object
;
261 const char *name
[2] = { "fini", "suspend" };
263 nvif_debug(object
, "%s notify\n", name
[suspend
]);
264 for (i
= 0; i
< ARRAY_SIZE(client
->notify
); i
++)
265 nvkm_client_notify_put(client
, i
);
266 return nvkm_object_fini(&client
->object
, suspend
);
270 nvkm_client_init(struct nvkm_client
*client
)
272 return nvkm_object_init(&client
->object
);
276 nvkm_client_del(struct nvkm_client
**pclient
)
278 struct nvkm_client
*client
= *pclient
;
281 nvkm_client_fini(client
, false);
282 for (i
= 0; i
< ARRAY_SIZE(client
->notify
); i
++)
283 nvkm_client_notify_del(client
, i
);
284 nvkm_object_dtor(&client
->object
);
291 nvkm_client_new(const char *name
, u64 device
, const char *cfg
,
292 const char *dbg
, struct nvkm_client
**pclient
)
294 struct nvkm_oclass oclass
= {};
295 struct nvkm_client
*client
;
297 if (!(client
= *pclient
= kzalloc(sizeof(*client
), GFP_KERNEL
)))
299 oclass
.client
= client
;
301 nvkm_object_ctor(&nvkm_client_object_func
, &oclass
, &client
->object
);
302 snprintf(client
->name
, sizeof(client
->name
), "%s", name
);
303 client
->device
= device
;
304 client
->debug
= nvkm_dbgopt(dbg
, "CLIENT");
305 client
->objroot
= RB_ROOT
;
306 client
->dmaroot
= RB_ROOT
;