diff options
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvif/client.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvif/driver.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvif/if0000.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvkm/core/client.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drm.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvif/Kbuild | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvif/client.c | 43 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvif/driver.c | 58 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/core/client.c | 50 |
9 files changed, 140 insertions, 35 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvif/client.h b/drivers/gpu/drm/nouveau/include/nvif/client.h index 4a7f6f7b836d..b52a8eadce01 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/client.h +++ b/drivers/gpu/drm/nouveau/include/nvif/client.h @@ -11,8 +11,7 @@ struct nvif_client { bool super; }; -int nvif_client_init(const char *drv, const char *name, u64 device, - const char *cfg, const char *dbg, +int nvif_client_init(struct nvif_client *parent, const char *name, u64 device, struct nvif_client *); void nvif_client_fini(struct nvif_client *); int nvif_client_ioctl(struct nvif_client *, void *, u32); diff --git a/drivers/gpu/drm/nouveau/include/nvif/driver.h b/drivers/gpu/drm/nouveau/include/nvif/driver.h index 8bd39e69229c..0c6f48d8140a 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/driver.h +++ b/drivers/gpu/drm/nouveau/include/nvif/driver.h @@ -1,5 +1,7 @@ #ifndef __NVIF_DRIVER_H__ #define __NVIF_DRIVER_H__ +#include <nvif/os.h> +struct nvif_client; struct nvif_driver { const char *name; @@ -14,9 +16,11 @@ struct nvif_driver { bool keep; }; +int nvif_driver_init(const char *drv, const char *cfg, const char *dbg, + const char *name, u64 device, struct nvif_client *); + extern const struct nvif_driver nvif_driver_nvkm; extern const struct nvif_driver nvif_driver_drm; extern const struct nvif_driver nvif_driver_lib; extern const struct nvif_driver nvif_driver_null; - #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0000.h b/drivers/gpu/drm/nouveau/include/nvif/if0000.h index 18bbd823677d..c2c0fc41e017 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0000.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0000.h @@ -1,6 +1,13 @@ #ifndef __NVIF_IF0000_H__ #define __NVIF_IF0000_H__ +struct nvif_client_v0 { + __u8 version; + __u8 pad01[7]; + __u64 device; + char name[32]; +}; + #define NVIF_CLIENT_V0_DEVLIST 0x00 struct nvif_client_devlist_v0 { diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h index e3b96e3df7da..e41231925109 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h @@ -23,6 +23,7 @@ int nvkm_client_new(const char *name, u64 device, const char *cfg, const char *dbg, int (*)(const void *, u32, const void *, u32), struct nvkm_client **); +struct nvkm_client *nvkm_client_search(struct nvkm_client *, u64 handle); int nvkm_client_notify_new(struct nvkm_object *, struct nvkm_event *, void *data, u32 size); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index dd7b52ab505a..279a96dc9a60 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -37,6 +37,8 @@ #include <core/pci.h> #include <core/tegra.h> +#include <nvif/driver.h> + #include <nvif/class.h> #include <nvif/cl0002.h> #include <nvif/cla06f.h> @@ -119,8 +121,8 @@ nouveau_cli_create(struct drm_device *dev, const char *sname, snprintf(cli->name, sizeof(cli->name), "%s", sname); cli->dev = dev; - ret = nvif_client_init(NULL, cli->name, nouveau_name(dev), - nouveau_config, nouveau_debug, + ret = nvif_driver_init(NULL, nouveau_config, nouveau_debug, + cli->name, nouveau_name(dev), &cli->base); if (ret == 0) { mutex_init(&cli->mutex); diff --git a/drivers/gpu/drm/nouveau/nvif/Kbuild b/drivers/gpu/drm/nouveau/nvif/Kbuild index ff8ed3a04d06..067b5e9f5ec1 100644 --- a/drivers/gpu/drm/nouveau/nvif/Kbuild +++ b/drivers/gpu/drm/nouveau/nvif/Kbuild @@ -1,4 +1,5 @@ nvif-y := nvif/object.o nvif-y += nvif/client.o nvif-y += nvif/device.o +nvif-y += nvif/driver.o nvif-y += nvif/notify.o diff --git a/drivers/gpu/drm/nouveau/nvif/client.c b/drivers/gpu/drm/nouveau/nvif/client.c index ad1307b6f783..12db54965c20 100644 --- a/drivers/gpu/drm/nouveau/nvif/client.c +++ b/drivers/gpu/drm/nouveau/nvif/client.c @@ -26,6 +26,9 @@ #include <nvif/driver.h> #include <nvif/ioctl.h> +#include <nvif/class.h> +#include <nvif/if0000.h> + int nvif_client_ioctl(struct nvif_client *client, void *data, u32 size) { @@ -55,29 +58,21 @@ nvif_client_fini(struct nvif_client *client) } } -static const struct nvif_driver * -nvif_drivers[] = { -#ifdef __KERNEL__ - &nvif_driver_nvkm, -#else - &nvif_driver_drm, - &nvif_driver_lib, - &nvif_driver_null, -#endif - NULL -}; - int -nvif_client_init(const char *driver, const char *name, u64 device, - const char *cfg, const char *dbg, struct nvif_client *client) +nvif_client_init(struct nvif_client *parent, const char *name, u64 device, + struct nvif_client *client) { + struct nvif_client_v0 args = { .device = device }; struct { struct nvif_ioctl_v0 ioctl; struct nvif_ioctl_nop_v0 nop; - } args = {}; - int ret, i; + } nop = {}; + int ret; - ret = nvif_object_init(NULL, 0, 0, NULL, 0, &client->object); + strncpy(args.name, name, sizeof(args.name)); + ret = nvif_object_init(parent != client ? &parent->object : NULL, + 0, NVIF_CLASS_CLIENT, &args, sizeof(args), + &client->object); if (ret) return ret; @@ -85,19 +80,11 @@ nvif_client_init(const char *driver, const char *name, u64 device, client->object.handle = ~0; client->route = NVIF_IOCTL_V0_ROUTE_NVIF; client->super = true; - - for (i = 0, ret = -EINVAL; (client->driver = nvif_drivers[i]); i++) { - if (!driver || !strcmp(client->driver->name, driver)) { - ret = client->driver->init(name, device, cfg, dbg, - &client->object.priv); - if (!ret || driver) - break; - } - } + client->driver = parent->driver; if (ret == 0) { - ret = nvif_client_ioctl(client, &args, sizeof(args)); - client->version = args.nop.version; + ret = nvif_client_ioctl(client, &nop, sizeof(nop)); + client->version = nop.nop.version; } if (ret) diff --git a/drivers/gpu/drm/nouveau/nvif/driver.c b/drivers/gpu/drm/nouveau/nvif/driver.c new file mode 100644 index 000000000000..701330956e33 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvif/driver.c @@ -0,0 +1,58 @@ +/* + * Copyright 2016 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ +#include <nvif/driver.h> +#include <nvif/client.h> + +static const struct nvif_driver * +nvif_driver[] = { +#ifdef __KERNEL__ + &nvif_driver_nvkm, +#else + &nvif_driver_drm, + &nvif_driver_lib, + &nvif_driver_null, +#endif + NULL +}; + +int +nvif_driver_init(const char *drv, const char *cfg, const char *dbg, + const char *name, u64 device, struct nvif_client *client) +{ + int ret = -EINVAL, i; + + for (i = 0; (client->driver = nvif_driver[i]); i++) { + if (!drv || !strcmp(client->driver->name, drv)) { + ret = client->driver->init(name, device, cfg, dbg, + &client->object.priv); + if (ret == 0) + break; + client->driver->fini(client->object.priv); + } + } + + if (ret == 0) + ret = nvif_client_init(client, name, device, client); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c index 4e2730cb1fec..0d3a896892b4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/client.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c @@ -31,9 +31,41 @@ #include <nvif/if0000.h> #include <nvif/unpack.h> -static const struct nvkm_sclass +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 { @@ -143,6 +175,19 @@ 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_client *client, void *data, u32 size) { @@ -196,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; } |