summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/core')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/client.c170
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/engine.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/ioctl.c78
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/mm.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/object.c64
5 files changed, 198 insertions, 124 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c
index e1943910858e..0d3a896892b4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/client.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c
@@ -31,6 +31,43 @@
#include <nvif/if0000.h>
#include <nvif/unpack.h>
+static int
+nvkm_uclient_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
+ struct nvkm_object **pobject)
+{
+ union {
+ struct nvif_client_v0 v0;
+ } *args = argv;
+ struct nvkm_client *client;
+ int ret = -ENOSYS;
+
+ if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))){
+ args->v0.name[sizeof(args->v0.name) - 1] = 0;
+ ret = nvkm_client_new(args->v0.name, args->v0.device, NULL,
+ NULL, oclass->client->ntfy, &client);
+ if (ret)
+ return ret;
+ } else
+ return ret;
+
+ client->object.client = oclass->client;
+ client->object.handle = oclass->handle;
+ client->object.route = oclass->route;
+ client->object.token = oclass->token;
+ client->object.object = oclass->object;
+ client->debug = oclass->client->debug;
+ *pobject = &client->object;
+ return 0;
+}
+
+const struct nvkm_sclass
+nvkm_uclient_sclass = {
+ .oclass = NVIF_CLASS_CLIENT,
+ .minver = 0,
+ .maxver = 0,
+ .ctor = nvkm_uclient_new,
+};
+
struct nvkm_client_notify {
struct nvkm_client *client;
struct nvkm_notify n;
@@ -138,17 +175,30 @@ nvkm_client_notify_new(struct nvkm_object *object,
return ret;
}
+static const struct nvkm_object_func nvkm_client;
+struct nvkm_client *
+nvkm_client_search(struct nvkm_client *client, u64 handle)
+{
+ struct nvkm_object *object;
+
+ object = nvkm_object_search(client, handle, &nvkm_client);
+ if (IS_ERR(object))
+ return (void *)object;
+
+ return nvkm_client(object);
+}
+
static int
-nvkm_client_mthd_devlist(struct nvkm_object *object, void *data, u32 size)
+nvkm_client_mthd_devlist(struct nvkm_client *client, void *data, u32 size)
{
union {
- struct nv_client_devlist_v0 v0;
+ struct nvif_client_devlist_v0 v0;
} *args = data;
int ret = -ENOSYS;
- nvif_ioctl(object, "client devlist size %d\n", size);
+ nvif_ioctl(&client->object, "client devlist size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
- nvif_ioctl(object, "client devlist vers %d count %d\n",
+ nvif_ioctl(&client->object, "client devlist vers %d count %d\n",
args->v0.version, args->v0.count);
if (size == sizeof(args->v0.device[0]) * args->v0.count) {
ret = nvkm_device_list(args->v0.device, args->v0.count);
@@ -167,9 +217,10 @@ nvkm_client_mthd_devlist(struct nvkm_object *object, void *data, u32 size)
static int
nvkm_client_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
{
+ struct nvkm_client *client = nvkm_client(object);
switch (mthd) {
- case NV_CLIENT_DEVLIST:
- return nvkm_client_mthd_devlist(object, data, size);
+ case NVIF_CLIENT_V0_DEVLIST:
+ return nvkm_client_mthd_devlist(client, data, size);
default:
break;
}
@@ -190,7 +241,8 @@ nvkm_client_child_get(struct nvkm_object *object, int index,
const struct nvkm_sclass *sclass;
switch (index) {
- case 0: sclass = &nvkm_udevice_sclass; break;
+ case 0: sclass = &nvkm_uclient_sclass; break;
+ case 1: sclass = &nvkm_udevice_sclass; break;
default:
return -EINVAL;
}
@@ -200,110 +252,54 @@ nvkm_client_child_get(struct nvkm_object *object, int index,
return 0;
}
-static const struct nvkm_object_func
-nvkm_client_object_func = {
- .mthd = nvkm_client_mthd,
- .sclass = nvkm_client_child_get,
-};
-
-void
-nvkm_client_remove(struct nvkm_client *client, struct nvkm_object *object)
-{
- if (!RB_EMPTY_NODE(&object->node))
- rb_erase(&object->node, &client->objroot);
-}
-
-bool
-nvkm_client_insert(struct nvkm_client *client, struct nvkm_object *object)
-{
- struct rb_node **ptr = &client->objroot.rb_node;
- struct rb_node *parent = NULL;
-
- while (*ptr) {
- struct nvkm_object *this =
- container_of(*ptr, typeof(*this), node);
- parent = *ptr;
- if (object->object < this->object)
- ptr = &parent->rb_left;
- else
- if (object->object > this->object)
- ptr = &parent->rb_right;
- else
- return false;
- }
-
- rb_link_node(&object->node, parent, ptr);
- rb_insert_color(&object->node, &client->objroot);
- return true;
-}
-
-struct nvkm_object *
-nvkm_client_search(struct nvkm_client *client, u64 handle)
-{
- struct rb_node *node = client->objroot.rb_node;
- while (node) {
- struct nvkm_object *object =
- container_of(node, typeof(*object), node);
- if (handle < object->object)
- node = node->rb_left;
- else
- if (handle > object->object)
- node = node->rb_right;
- else
- return object;
- }
- return NULL;
-}
-
-int
-nvkm_client_fini(struct nvkm_client *client, bool suspend)
+static int
+nvkm_client_fini(struct nvkm_object *object, bool suspend)
{
- struct nvkm_object *object = &client->object;
+ struct nvkm_client *client = nvkm_client(object);
const char *name[2] = { "fini", "suspend" };
int i;
nvif_debug(object, "%s notify\n", name[suspend]);
for (i = 0; i < ARRAY_SIZE(client->notify); i++)
nvkm_client_notify_put(client, i);
- return nvkm_object_fini(&client->object, suspend);
-}
-
-int
-nvkm_client_init(struct nvkm_client *client)
-{
- return nvkm_object_init(&client->object);
+ return 0;
}
-void
-nvkm_client_del(struct nvkm_client **pclient)
+static void *
+nvkm_client_dtor(struct nvkm_object *object)
{
- struct nvkm_client *client = *pclient;
+ struct nvkm_client *client = nvkm_client(object);
int i;
- if (client) {
- nvkm_client_fini(client, false);
- for (i = 0; i < ARRAY_SIZE(client->notify); i++)
- nvkm_client_notify_del(client, i);
- nvkm_object_dtor(&client->object);
- kfree(*pclient);
- *pclient = NULL;
- }
+ for (i = 0; i < ARRAY_SIZE(client->notify); i++)
+ nvkm_client_notify_del(client, i);
+ return client;
}
+static const struct nvkm_object_func
+nvkm_client = {
+ .dtor = nvkm_client_dtor,
+ .fini = nvkm_client_fini,
+ .mthd = nvkm_client_mthd,
+ .sclass = nvkm_client_child_get,
+};
+
int
nvkm_client_new(const char *name, u64 device, const char *cfg,
- const char *dbg, struct nvkm_client **pclient)
+ const char *dbg,
+ int (*ntfy)(const void *, u32, const void *, u32),
+ struct nvkm_client **pclient)
{
- struct nvkm_oclass oclass = {};
+ struct nvkm_oclass oclass = { .base = nvkm_uclient_sclass };
struct nvkm_client *client;
if (!(client = *pclient = kzalloc(sizeof(*client), GFP_KERNEL)))
return -ENOMEM;
oclass.client = client;
- nvkm_object_ctor(&nvkm_client_object_func, &oclass, &client->object);
+ nvkm_object_ctor(&nvkm_client, &oclass, &client->object);
snprintf(client->name, sizeof(client->name), "%s", name);
client->device = device;
client->debug = nvkm_dbgopt(dbg, "CLIENT");
client->objroot = RB_ROOT;
- client->dmaroot = RB_ROOT;
+ client->ntfy = ntfy;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/engine.c b/drivers/gpu/drm/nouveau/nvkm/core/engine.c
index ee8e5831fe37..b6c916954a10 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/engine.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/engine.c
@@ -27,6 +27,14 @@
#include <subdev/fb.h>
+bool
+nvkm_engine_chsw_load(struct nvkm_engine *engine)
+{
+ if (engine->func->chsw_load)
+ return engine->func->chsw_load(engine);
+ return false;
+}
+
void
nvkm_engine_unref(struct nvkm_engine **pengine)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
index b0db51847c36..be19bbe56bba 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
@@ -29,7 +29,8 @@
#include <nvif/ioctl.h>
static int
-nvkm_ioctl_nop(struct nvkm_object *object, void *data, u32 size)
+nvkm_ioctl_nop(struct nvkm_client *client,
+ struct nvkm_object *object, void *data, u32 size)
{
union {
struct nvif_ioctl_nop_v0 v0;
@@ -46,7 +47,8 @@ nvkm_ioctl_nop(struct nvkm_object *object, void *data, u32 size)
}
static int
-nvkm_ioctl_sclass(struct nvkm_object *object, void *data, u32 size)
+nvkm_ioctl_sclass(struct nvkm_client *client,
+ struct nvkm_object *object, void *data, u32 size)
{
union {
struct nvif_ioctl_sclass_v0 v0;
@@ -78,12 +80,12 @@ nvkm_ioctl_sclass(struct nvkm_object *object, void *data, u32 size)
}
static int
-nvkm_ioctl_new(struct nvkm_object *parent, void *data, u32 size)
+nvkm_ioctl_new(struct nvkm_client *client,
+ struct nvkm_object *parent, void *data, u32 size)
{
union {
struct nvif_ioctl_new_v0 v0;
} *args = data;
- struct nvkm_client *client = parent->client;
struct nvkm_object *object = NULL;
struct nvkm_oclass oclass;
int ret = -ENOSYS, i = 0;
@@ -104,9 +106,11 @@ nvkm_ioctl_new(struct nvkm_object *parent, void *data, u32 size)
do {
memset(&oclass, 0x00, sizeof(oclass));
- oclass.client = client;
oclass.handle = args->v0.handle;
+ oclass.route = args->v0.route;
+ oclass.token = args->v0.token;
oclass.object = args->v0.object;
+ oclass.client = client;
oclass.parent = parent;
ret = parent->func->sclass(parent, i++, &oclass);
if (ret)
@@ -125,10 +129,7 @@ nvkm_ioctl_new(struct nvkm_object *parent, void *data, u32 size)
ret = nvkm_object_init(object);
if (ret == 0) {
list_add(&object->head, &parent->tree);
- object->route = args->v0.route;
- object->token = args->v0.token;
- object->object = args->v0.object;
- if (nvkm_client_insert(client, object)) {
+ if (nvkm_object_insert(object)) {
client->data = object;
return 0;
}
@@ -142,7 +143,8 @@ nvkm_ioctl_new(struct nvkm_object *parent, void *data, u32 size)
}
static int
-nvkm_ioctl_del(struct nvkm_object *object, void *data, u32 size)
+nvkm_ioctl_del(struct nvkm_client *client,
+ struct nvkm_object *object, void *data, u32 size)
{
union {
struct nvif_ioctl_del none;
@@ -156,11 +158,12 @@ nvkm_ioctl_del(struct nvkm_object *object, void *data, u32 size)
nvkm_object_del(&object);
}
- return ret;
+ return ret ? ret : 1;
}
static int
-nvkm_ioctl_mthd(struct nvkm_object *object, void *data, u32 size)
+nvkm_ioctl_mthd(struct nvkm_client *client,
+ struct nvkm_object *object, void *data, u32 size)
{
union {
struct nvif_ioctl_mthd_v0 v0;
@@ -179,7 +182,8 @@ nvkm_ioctl_mthd(struct nvkm_object *object, void *data, u32 size)
static int
-nvkm_ioctl_rd(struct nvkm_object *object, void *data, u32 size)
+nvkm_ioctl_rd(struct nvkm_client *client,
+ struct nvkm_object *object, void *data, u32 size)
{
union {
struct nvif_ioctl_rd_v0 v0;
@@ -218,7 +222,8 @@ nvkm_ioctl_rd(struct nvkm_object *object, void *data, u32 size)
}
static int
-nvkm_ioctl_wr(struct nvkm_object *object, void *data, u32 size)
+nvkm_ioctl_wr(struct nvkm_client *client,
+ struct nvkm_object *object, void *data, u32 size)
{
union {
struct nvif_ioctl_wr_v0 v0;
@@ -246,7 +251,8 @@ nvkm_ioctl_wr(struct nvkm_object *object, void *data, u32 size)
}
static int
-nvkm_ioctl_map(struct nvkm_object *object, void *data, u32 size)
+nvkm_ioctl_map(struct nvkm_client *client,
+ struct nvkm_object *object, void *data, u32 size)
{
union {
struct nvif_ioctl_map_v0 v0;
@@ -264,7 +270,8 @@ nvkm_ioctl_map(struct nvkm_object *object, void *data, u32 size)
}
static int
-nvkm_ioctl_unmap(struct nvkm_object *object, void *data, u32 size)
+nvkm_ioctl_unmap(struct nvkm_client *client,
+ struct nvkm_object *object, void *data, u32 size)
{
union {
struct nvif_ioctl_unmap none;
@@ -280,7 +287,8 @@ nvkm_ioctl_unmap(struct nvkm_object *object, void *data, u32 size)
}
static int
-nvkm_ioctl_ntfy_new(struct nvkm_object *object, void *data, u32 size)
+nvkm_ioctl_ntfy_new(struct nvkm_client *client,
+ struct nvkm_object *object, void *data, u32 size)
{
union {
struct nvif_ioctl_ntfy_new_v0 v0;
@@ -306,9 +314,9 @@ nvkm_ioctl_ntfy_new(struct nvkm_object *object, void *data, u32 size)
}
static int
-nvkm_ioctl_ntfy_del(struct nvkm_object *object, void *data, u32 size)
+nvkm_ioctl_ntfy_del(struct nvkm_client *client,
+ struct nvkm_object *object, void *data, u32 size)
{
- struct nvkm_client *client = object->client;
union {
struct nvif_ioctl_ntfy_del_v0 v0;
} *args = data;
@@ -325,9 +333,9 @@ nvkm_ioctl_ntfy_del(struct nvkm_object *object, void *data, u32 size)
}
static int
-nvkm_ioctl_ntfy_get(struct nvkm_object *object, void *data, u32 size)
+nvkm_ioctl_ntfy_get(struct nvkm_client *client,
+ struct nvkm_object *object, void *data, u32 size)
{
- struct nvkm_client *client = object->client;
union {
struct nvif_ioctl_ntfy_get_v0 v0;
} *args = data;
@@ -344,9 +352,9 @@ nvkm_ioctl_ntfy_get(struct nvkm_object *object, void *data, u32 size)
}
static int
-nvkm_ioctl_ntfy_put(struct nvkm_object *object, void *data, u32 size)
+nvkm_ioctl_ntfy_put(struct nvkm_client *client,
+ struct nvkm_object *object, void *data, u32 size)
{
- struct nvkm_client *client = object->client;
union {
struct nvif_ioctl_ntfy_put_v0 v0;
} *args = data;
@@ -364,7 +372,7 @@ nvkm_ioctl_ntfy_put(struct nvkm_object *object, void *data, u32 size)
static struct {
int version;
- int (*func)(struct nvkm_object *, void *, u32);
+ int (*func)(struct nvkm_client *, struct nvkm_object *, void *, u32);
}
nvkm_ioctl_v0[] = {
{ 0x00, nvkm_ioctl_nop },
@@ -389,13 +397,10 @@ nvkm_ioctl_path(struct nvkm_client *client, u64 handle, u32 type,
struct nvkm_object *object;
int ret;
- if (handle)
- object = nvkm_client_search(client, handle);
- else
- object = &client->object;
- if (unlikely(!object)) {
+ object = nvkm_object_search(client, handle, NULL);
+ if (IS_ERR(object)) {
nvif_ioctl(&client->object, "object not found\n");
- return -ENOENT;
+ return PTR_ERR(object);
}
if (owner != NVIF_IOCTL_V0_OWNER_ANY && owner != object->route) {
@@ -407,7 +412,7 @@ nvkm_ioctl_path(struct nvkm_client *client, u64 handle, u32 type,
if (ret = -EINVAL, type < ARRAY_SIZE(nvkm_ioctl_v0)) {
if (nvkm_ioctl_v0[type].version == 0)
- ret = nvkm_ioctl_v0[type].func(object, data, size);
+ ret = nvkm_ioctl_v0[type].func(client, object, data, size);
}
return ret;
@@ -436,12 +441,13 @@ nvkm_ioctl(struct nvkm_client *client, bool supervisor,
&args->v0.route, &args->v0.token);
}
- nvif_ioctl(object, "return %d\n", ret);
- if (hack) {
- *hack = client->data;
- client->data = NULL;
+ if (ret != 1) {
+ nvif_ioctl(object, "return %d\n", ret);
+ if (hack) {
+ *hack = client->data;
+ client->data = NULL;
+ }
}
- client->super = false;
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/mm.c b/drivers/gpu/drm/nouveau/nvkm/core/mm.c
index 09a1eee8fd33..fd19d652a7ab 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/mm.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/mm.c
@@ -147,6 +147,7 @@ nvkm_mm_head(struct nvkm_mm *mm, u8 heap, u8 type, u32 size_max, u32 size_min,
if (!this)
return -ENOMEM;
+ this->next = NULL;
this->type = type;
list_del(&this->fl_entry);
*pnode = this;
@@ -225,6 +226,7 @@ nvkm_mm_tail(struct nvkm_mm *mm, u8 heap, u8 type, u32 size_max, u32 size_min,
if (!this)
return -ENOMEM;
+ this->next = NULL;
this->type = type;
list_del(&this->fl_entry);
*pnode = this;
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/object.c b/drivers/gpu/drm/nouveau/nvkm/core/object.c
index 67aa7223dcd7..89d2e9da11c7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/object.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c
@@ -25,6 +25,65 @@
#include <core/client.h>
#include <core/engine.h>
+struct nvkm_object *
+nvkm_object_search(struct nvkm_client *client, u64 handle,
+ const struct nvkm_object_func *func)
+{
+ struct nvkm_object *object;
+
+ if (handle) {
+ struct rb_node *node = client->objroot.rb_node;
+ while (node) {
+ object = rb_entry(node, typeof(*object), node);
+ if (handle < object->object)
+ node = node->rb_left;
+ else
+ if (handle > object->object)
+ node = node->rb_right;
+ else
+ goto done;
+ }
+ return ERR_PTR(-ENOENT);
+ } else {
+ object = &client->object;
+ }
+
+done:
+ if (unlikely(func && object->func != func))
+ return ERR_PTR(-EINVAL);
+ return object;
+}
+
+void
+nvkm_object_remove(struct nvkm_object *object)
+{
+ if (!RB_EMPTY_NODE(&object->node))
+ rb_erase(&object->node, &object->client->objroot);
+}
+
+bool
+nvkm_object_insert(struct nvkm_object *object)
+{
+ struct rb_node **ptr = &object->client->objroot.rb_node;
+ struct rb_node *parent = NULL;
+
+ while (*ptr) {
+ struct nvkm_object *this = rb_entry(*ptr, typeof(*this), node);
+ parent = *ptr;
+ if (object->object < this->object)
+ ptr = &parent->rb_left;
+ else
+ if (object->object > this->object)
+ ptr = &parent->rb_right;
+ else
+ return false;
+ }
+
+ rb_link_node(&object->node, parent, ptr);
+ rb_insert_color(&object->node, &object->client->objroot);
+ return true;
+}
+
int
nvkm_object_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
{
@@ -214,7 +273,7 @@ nvkm_object_del(struct nvkm_object **pobject)
struct nvkm_object *object = *pobject;
if (object && !WARN_ON(!object->func)) {
*pobject = nvkm_object_dtor(object);
- nvkm_client_remove(object->client, object);
+ nvkm_object_remove(object);
list_del(&object->head);
kfree(*pobject);
*pobject = NULL;
@@ -230,6 +289,9 @@ nvkm_object_ctor(const struct nvkm_object_func *func,
object->engine = nvkm_engine_ref(oclass->engine);
object->oclass = oclass->base.oclass;
object->handle = oclass->handle;
+ object->route = oclass->route;
+ object->token = oclass->token;
+ object->object = oclass->object;
INIT_LIST_HEAD(&object->head);
INIT_LIST_HEAD(&object->tree);
RB_CLEAR_NODE(&object->node);