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/handle.h>
27 #include <core/notify.h>
28 #include <core/option.h>
30 #include <nvif/class.h>
31 #include <nvif/event.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
= nvkm_client(object
);
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 nv_ioctl(client
, "notify new size %d\n", size
);
115 if (nvif_unpack(req
->v0
, 0, 0, true)) {
116 nv_ioctl(client
, "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 nv_ioctl(object
, "client devlist size %d\n", size
);
150 if (nvif_unpack(args
->v0
, 0, 0, true)) {
151 nv_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_dtor(struct nvkm_object
*object
)
182 struct nvkm_client
*client
= (void *)object
;
184 for (i
= 0; i
< ARRAY_SIZE(client
->notify
); i
++)
185 nvkm_client_notify_del(client
, i
);
186 nvkm_object_ref(NULL
, &client
->device
);
187 nvkm_handle_destroy(client
->root
);
188 nvkm_namedb_destroy(&client
->namedb
);
191 static struct nvkm_oclass
192 nvkm_client_oclass
= {
193 .ofuncs
= &(struct nvkm_ofuncs
) {
194 .dtor
= nvkm_client_dtor
,
195 .mthd
= nvkm_client_mthd
,
200 nvkm_client_create_(const char *name
, u64 devname
, const char *cfg
,
201 const char *dbg
, int length
, void **pobject
)
203 struct nvkm_object
*device
;
204 struct nvkm_client
*client
;
207 device
= (void *)nvkm_device_find(devname
);
211 ret
= nvkm_namedb_create_(NULL
, NULL
, &nvkm_client_oclass
,
212 NV_CLIENT_CLASS
, NULL
,
213 (1ULL << NVDEV_ENGINE_DEVICE
),
219 ret
= nvkm_handle_create(nv_object(client
), ~0, ~0, nv_object(client
),
224 /* prevent init/fini being called, os in in charge of this */
225 atomic_set(&nv_object(client
)->usecount
, 2);
227 nvkm_object_ref(device
, &client
->device
);
228 snprintf(client
->name
, sizeof(client
->name
), "%s", name
);
229 client
->debug
= nvkm_dbgopt(dbg
, "CLIENT");
234 nvkm_client_init(struct nvkm_client
*client
)
237 nv_debug(client
, "init running\n");
238 ret
= nvkm_handle_init(client
->root
);
239 nv_debug(client
, "init completed with %d\n", ret
);
244 nvkm_client_fini(struct nvkm_client
*client
, bool suspend
)
246 const char *name
[2] = { "fini", "suspend" };
248 nv_debug(client
, "%s running\n", name
[suspend
]);
249 nv_debug(client
, "%s notify\n", name
[suspend
]);
250 for (i
= 0; i
< ARRAY_SIZE(client
->notify
); i
++)
251 nvkm_client_notify_put(client
, i
);
252 nv_debug(client
, "%s object\n", name
[suspend
]);
253 ret
= nvkm_handle_fini(client
->root
, suspend
);
254 nv_debug(client
, "%s completed with %d\n", name
[suspend
], ret
);
259 nvkm_client_name(void *obj
)
261 const char *client_name
= "unknown";
262 struct nvkm_client
*client
= nvkm_client(obj
);
264 client_name
= client
->name
;