Commit 8ec2a6ec authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/core: import ioctl/event interfaces

This forms the basis for the new APIs that will be exposed to userspace,
giving it access to:

- Object method calls, the immediately useful of which is performance
  counters and the abiity to manipulate the ZBC tables.
- Information on the child classes an object supports, in order to avoid
  having to try all supported classes until successful.
- Notifications, which will be used in the future to inform the client
  if its channel was killed due to a lockup, etc.

This commit imports the interfaces, but are not currently used.  The DRM
portion of the driver will be ported to speak to the core using these
interfaces as much as possible.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 29dff2f5
...@@ -14,6 +14,7 @@ nouveau-y += core/core/enum.o ...@@ -14,6 +14,7 @@ nouveau-y += core/core/enum.o
nouveau-y += core/core/event.o nouveau-y += core/core/event.o
nouveau-y += core/core/gpuobj.o nouveau-y += core/core/gpuobj.o
nouveau-y += core/core/handle.o nouveau-y += core/core/handle.o
nouveau-y += core/core/ioctl.o
nouveau-y += core/core/mm.o nouveau-y += core/core/mm.o
nouveau-y += core/core/namedb.o nouveau-y += core/core/namedb.o
nouveau-y += core/core/notify.o nouveau-y += core/core/notify.o
......
...@@ -27,12 +27,124 @@ ...@@ -27,12 +27,124 @@
#include <core/handle.h> #include <core/handle.h>
#include <core/option.h> #include <core/option.h>
#include <nvif/unpack.h>
#include <nvif/event.h>
#include <engine/device.h> #include <engine/device.h>
struct nvkm_client_notify {
struct nouveau_client *client;
struct nvkm_notify n;
u8 version;
u8 size;
union {
struct nvif_notify_rep_v0 v0;
} rep;
};
static int
nvkm_client_notify(struct nvkm_notify *n)
{
struct nvkm_client_notify *notify = container_of(n, typeof(*notify), n);
struct nouveau_client *client = notify->client;
return client->ntfy(&notify->rep, notify->size, n->data, n->size);
}
int
nvkm_client_notify_put(struct nouveau_client *client, int index)
{
if (index < ARRAY_SIZE(client->notify)) {
if (client->notify[index]) {
nvkm_notify_put(&client->notify[index]->n);
return 0;
}
}
return -ENOENT;
}
int
nvkm_client_notify_get(struct nouveau_client *client, int index)
{
if (index < ARRAY_SIZE(client->notify)) {
if (client->notify[index]) {
nvkm_notify_get(&client->notify[index]->n);
return 0;
}
}
return -ENOENT;
}
int
nvkm_client_notify_del(struct nouveau_client *client, int index)
{
if (index < ARRAY_SIZE(client->notify)) {
if (client->notify[index]) {
nvkm_notify_fini(&client->notify[index]->n);
kfree(client->notify[index]);
client->notify[index] = NULL;
return 0;
}
}
return -ENOENT;
}
int
nvkm_client_notify_new(struct nouveau_client *client,
struct nvkm_event *event, void *data, u32 size)
{
struct nvkm_client_notify *notify;
union {
struct nvif_notify_req_v0 v0;
} *req = data;
u8 index, reply;
int ret;
for (index = 0; index < ARRAY_SIZE(client->notify); index++) {
if (!client->notify[index])
break;
}
if (index == ARRAY_SIZE(client->notify))
return -ENOSPC;
notify = kzalloc(sizeof(*notify), GFP_KERNEL);
if (!notify)
return -ENOMEM;
nv_ioctl(client, "notify new size %d\n", size);
if (nvif_unpack(req->v0, 0, 0, true)) {
nv_ioctl(client, "notify new vers %d reply %d route %02x "
"token %llx\n", req->v0.version,
req->v0.reply, req->v0.route, req->v0.token);
notify->version = req->v0.version;
notify->size = sizeof(notify->rep.v0);
notify->rep.v0.version = req->v0.version;
notify->rep.v0.route = req->v0.route;
notify->rep.v0.token = req->v0.token;
reply = req->v0.reply;
}
if (ret == 0) {
ret = nvkm_notify_init(event, nvkm_client_notify, false,
data, size, reply, &notify->n);
if (ret == 0) {
client->notify[index] = notify;
notify->client = client;
return 0;
}
}
kfree(notify);
return 0;
}
static void static void
nouveau_client_dtor(struct nouveau_object *object) nouveau_client_dtor(struct nouveau_object *object)
{ {
struct nouveau_client *client = (void *)object; struct nouveau_client *client = (void *)object;
int i;
for (i = 0; i < ARRAY_SIZE(client->notify); i++)
nvkm_client_notify_del(client, i);
nouveau_object_ref(NULL, &client->device); nouveau_object_ref(NULL, &client->device);
nouveau_handle_destroy(client->root); nouveau_handle_destroy(client->root);
nouveau_namedb_destroy(&client->base); nouveau_namedb_destroy(&client->base);
...@@ -93,9 +205,12 @@ int ...@@ -93,9 +205,12 @@ int
nouveau_client_fini(struct nouveau_client *client, bool suspend) nouveau_client_fini(struct nouveau_client *client, bool suspend)
{ {
const char *name[2] = { "fini", "suspend" }; const char *name[2] = { "fini", "suspend" };
int ret; int ret, i;
nv_debug(client, "%s running\n", name[suspend]); nv_debug(client, "%s running\n", name[suspend]);
nv_debug(client, "%s notify\n", name[suspend]);
for (i = 0; i < ARRAY_SIZE(client->notify); i++)
nvkm_client_notify_put(client, i);
nv_debug(client, "%s object\n", name[suspend]);
ret = nouveau_handle_fini(client->root, suspend); ret = nouveau_handle_fini(client->root, suspend);
nv_debug(client, "%s completed with %d\n", name[suspend], ret); nv_debug(client, "%s completed with %d\n", name[suspend], ret);
return ret; return ret;
......
This diff is collapsed.
...@@ -22,10 +22,13 @@ ...@@ -22,10 +22,13 @@
* Authors: Ben Skeggs <bskeggs@redhat.com> * Authors: Ben Skeggs <bskeggs@redhat.com>
*/ */
#include <core/os.h> #include <core/client.h>
#include <core/event.h> #include <core/event.h>
#include <core/notify.h> #include <core/notify.h>
#include <nvif/unpack.h>
#include <nvif/event.h>
static inline void static inline void
nvkm_notify_put_locked(struct nvkm_notify *notify) nvkm_notify_put_locked(struct nvkm_notify *notify)
{ {
......
...@@ -10,6 +10,11 @@ struct nouveau_client { ...@@ -10,6 +10,11 @@ struct nouveau_client {
char name[32]; char name[32];
u32 debug; u32 debug;
struct nouveau_vm *vm; struct nouveau_vm *vm;
bool super;
void *data;
int (*ntfy)(const void *, u32, const void *, u32);
struct nvkm_client_notify *notify[8];
}; };
static inline struct nouveau_client * static inline struct nouveau_client *
...@@ -43,4 +48,10 @@ int nouveau_client_init(struct nouveau_client *); ...@@ -43,4 +48,10 @@ int nouveau_client_init(struct nouveau_client *);
int nouveau_client_fini(struct nouveau_client *, bool suspend); int nouveau_client_fini(struct nouveau_client *, bool suspend);
const char *nouveau_client_name(void *obj); const char *nouveau_client_name(void *obj);
int nvkm_client_notify_new(struct nouveau_client *, struct nvkm_event *,
void *data, u32 size);
int nvkm_client_notify_del(struct nouveau_client *, int index);
int nvkm_client_notify_get(struct nouveau_client *, int index);
int nvkm_client_notify_put(struct nouveau_client *, int index);
#endif #endif
...@@ -10,6 +10,9 @@ struct nouveau_handle { ...@@ -10,6 +10,9 @@ struct nouveau_handle {
u32 name; u32 name;
u32 priv; u32 priv;
u8 route;
u64 token;
struct nouveau_handle *parent; struct nouveau_handle *parent;
struct nouveau_object *object; struct nouveau_object *object;
}; };
......
#ifndef __NVKM_IOCTL_H__
#define __NVKM_IOCTL_H__
int nvkm_ioctl(struct nouveau_client *, bool, void *, u32, void **);
#endif
...@@ -15,7 +15,7 @@ struct nvkm_notify { ...@@ -15,7 +15,7 @@ struct nvkm_notify {
/* set by nvkm_event ctor */ /* set by nvkm_event ctor */
u32 types; u32 types;
int index; int index;
u8 size; u32 size;
struct work_struct work; struct work_struct work;
/* this is const for a *very* good reason - the data might be on the /* this is const for a *very* good reason - the data might be on the
......
...@@ -78,6 +78,7 @@ struct nouveau_omthds { ...@@ -78,6 +78,7 @@ struct nouveau_omthds {
int (*call)(struct nouveau_object *, u32, void *, u32); int (*call)(struct nouveau_object *, u32, void *, u32);
}; };
struct nvkm_event;
struct nouveau_ofuncs { struct nouveau_ofuncs {
int (*ctor)(struct nouveau_object *, struct nouveau_object *, int (*ctor)(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, void *data, u32 size, struct nouveau_oclass *, void *data, u32 size,
...@@ -85,6 +86,9 @@ struct nouveau_ofuncs { ...@@ -85,6 +86,9 @@ struct nouveau_ofuncs {
void (*dtor)(struct nouveau_object *); void (*dtor)(struct nouveau_object *);
int (*init)(struct nouveau_object *); int (*init)(struct nouveau_object *);
int (*fini)(struct nouveau_object *, bool suspend); int (*fini)(struct nouveau_object *, bool suspend);
int (*mthd)(struct nouveau_object *, u32, void *, u32);
int (*ntfy)(struct nouveau_object *, u32, struct nvkm_event **);
int (* map)(struct nouveau_object *, u64 *, u32 *);
u8 (*rd08)(struct nouveau_object *, u64 offset); u8 (*rd08)(struct nouveau_object *, u64 offset);
u16 (*rd16)(struct nouveau_object *, u64 offset); u16 (*rd16)(struct nouveau_object *, u64 offset);
u32 (*rd32)(struct nouveau_object *, u64 offset); u32 (*rd32)(struct nouveau_object *, u64 offset);
......
...@@ -21,6 +21,7 @@ nv_printk_(struct nouveau_object *, int, const char *, ...); ...@@ -21,6 +21,7 @@ nv_printk_(struct nouveau_object *, int, const char *, ...);
#define nv_debug(o,f,a...) nv_printk((o), DEBUG, f, ##a) #define nv_debug(o,f,a...) nv_printk((o), DEBUG, f, ##a)
#define nv_trace(o,f,a...) nv_printk((o), TRACE, f, ##a) #define nv_trace(o,f,a...) nv_printk((o), TRACE, f, ##a)
#define nv_spam(o,f,a...) nv_printk((o), SPAM, f, ##a) #define nv_spam(o,f,a...) nv_printk((o), SPAM, f, ##a)
#define nv_ioctl(o,f,a...) nv_trace(nouveau_client(o), "ioctl: "f, ##a)
#define nv_assert(f,a...) do { \ #define nv_assert(f,a...) do { \
if (NV_DBG_FATAL <= CONFIG_NOUVEAU_DEBUG) \ if (NV_DBG_FATAL <= CONFIG_NOUVEAU_DEBUG) \
......
../../../nvif/ioctl.h
\ No newline at end of file
#ifndef __NVIF_EVENT_H__ #ifndef __NVIF_EVENT_H__
#define __NVIF_EVENT_H__ #define __NVIF_EVENT_H__
struct nvif_notify_req_v0 {
__u8 version;
__u8 reply;
__u8 pad02[5];
#define NVIF_NOTIFY_V0_ROUTE_NVIF 0x00
__u8 route;
__u64 token; /* must be unique */
__u8 data[]; /* request data (below) */
};
struct nvif_notify_rep_v0 {
__u8 version;
__u8 pad01[6];
__u8 route;
__u64 token;
__u8 data[]; /* reply data (below) */
};
struct nvif_notify_head_req_v0 { struct nvif_notify_head_req_v0 {
/* nvif_notify_req ... */
__u8 version; __u8 version;
__u8 head; __u8 head;
__u8 pad02[6];
}; };
struct nvif_notify_head_rep_v0 { struct nvif_notify_head_rep_v0 {
/* nvif_notify_rep ... */
__u8 version; __u8 version;
__u8 pad01[7];
}; };
struct nvif_notify_conn_req_v0 { struct nvif_notify_conn_req_v0 {
/* nvif_notify_req ... */
__u8 version; __u8 version;
#define NVIF_NOTIFY_CONN_V0_PLUG 0x01 #define NVIF_NOTIFY_CONN_V0_PLUG 0x01
#define NVIF_NOTIFY_CONN_V0_UNPLUG 0x02 #define NVIF_NOTIFY_CONN_V0_UNPLUG 0x02
...@@ -18,11 +41,14 @@ struct nvif_notify_conn_req_v0 { ...@@ -18,11 +41,14 @@ struct nvif_notify_conn_req_v0 {
#define NVIF_NOTIFY_CONN_V0_ANY 0x07 #define NVIF_NOTIFY_CONN_V0_ANY 0x07
__u8 mask; __u8 mask;
__u8 conn; __u8 conn;
__u8 pad03[5];
}; };
struct nvif_notify_conn_rep_v0 { struct nvif_notify_conn_rep_v0 {
/* nvif_notify_rep ... */
__u8 version; __u8 version;
__u8 mask; __u8 mask;
__u8 pad02[6];
}; };
#endif #endif
#ifndef __NVIF_IOCTL_H__
#define __NVIF_IOCTL_H__
struct nvif_ioctl_v0 {
__u8 version;
#define NVIF_IOCTL_V0_OWNER_NVIF 0x00
#define NVIF_IOCTL_V0_OWNER_ANY 0xff
__u8 owner;
#define NVIF_IOCTL_V0_NOP 0x00
#define NVIF_IOCTL_V0_SCLASS 0x01
#define NVIF_IOCTL_V0_NEW 0x02
#define NVIF_IOCTL_V0_DEL 0x03
#define NVIF_IOCTL_V0_MTHD 0x04
#define NVIF_IOCTL_V0_RD 0x05
#define NVIF_IOCTL_V0_WR 0x06
#define NVIF_IOCTL_V0_MAP 0x07
#define NVIF_IOCTL_V0_UNMAP 0x08
#define NVIF_IOCTL_V0_NTFY_NEW 0x09
#define NVIF_IOCTL_V0_NTFY_DEL 0x0a
#define NVIF_IOCTL_V0_NTFY_GET 0x0b
#define NVIF_IOCTL_V0_NTFY_PUT 0x0c
__u8 type;
__u8 path_nr;
#define NVIF_IOCTL_V0_ROUTE_NVIF 0x00
#define NVIF_IOCTL_V0_ROUTE_HIDDEN 0xff
__u8 pad04[3];
__u8 route;
__u64 token;
__u32 path[8]; /* in reverse */
__u8 data[]; /* ioctl data (below) */
};
struct nvif_ioctl_nop {
};
struct nvif_ioctl_sclass_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 count;
__u8 pad02[6];
__u32 oclass[];
};
struct nvif_ioctl_new_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 pad01[6];
__u8 route;
__u64 token;
__u32 handle;
__u32 oclass;
__u8 data[]; /* class data (class.h) */
};
struct nvif_ioctl_del {
};
struct nvif_ioctl_rd_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 size;
__u8 pad02[2];
__u32 data;
__u64 addr;
};
struct nvif_ioctl_wr_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 size;
__u8 pad02[2];
__u32 data;
__u64 addr;
};
struct nvif_ioctl_map_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 pad01[3];
__u32 length;
__u64 handle;
};
struct nvif_ioctl_unmap {
};
struct nvif_ioctl_ntfy_new_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 event;
__u8 index;
__u8 pad03[5];
__u8 data[]; /* event request data (event.h) */
};
struct nvif_ioctl_ntfy_del_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 index;
__u8 pad02[6];
};
struct nvif_ioctl_ntfy_get_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 index;
__u8 pad02[6];
};
struct nvif_ioctl_ntfy_put_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 index;
__u8 pad02[6];
};
struct nvif_ioctl_mthd_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 method;
__u8 pad02[6];
__u8 data[]; /* method data (class.h) */
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment