drm/nouveau/device: convert user class to new-style nvkm_object

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2015-08-20 14:54:18 +10:00
parent 24bd0930be
commit 2a9f847f5d
7 changed files with 182 additions and 90 deletions

View File

@ -272,10 +272,10 @@ enum nv_bus_type {
NVKM_BUS_PLATFORM, NVKM_BUS_PLATFORM,
}; };
extern struct nvkm_ofuncs nvkm_udevice_ofuncs;
void nvkm_device_del(struct nvkm_device **); void nvkm_device_del(struct nvkm_device **);
extern const struct nvkm_sclass nvkm_udevice_sclass;
/* device logging */ /* device logging */
#define nvdev_printk_(d,l,p,f,a...) do { \ #define nvdev_printk_(d,l,p,f,a...) do { \
struct nvkm_device *_device = (d); \ struct nvkm_device *_device = (d); \

View File

@ -180,27 +180,26 @@ static int
nvkm_client_child_new(const struct nvkm_oclass *oclass, nvkm_client_child_new(const struct nvkm_oclass *oclass,
void *data, u32 size, struct nvkm_object **pobject) void *data, u32 size, struct nvkm_object **pobject)
{ {
static struct nvkm_oclass devobj = { return oclass->base.ctor(oclass, data, size, pobject);
.handle = NV_DEVICE,
.ofuncs = &nvkm_udevice_ofuncs,
};
return nvkm_object_old(oclass->parent, NULL, &devobj, data, size, pobject);
} }
static int static int
nvkm_client_child_get(struct nvkm_object *object, int index, nvkm_client_child_get(struct nvkm_object *object, int index,
struct nvkm_oclass *oclass) struct nvkm_oclass *oclass)
{ {
if (index == 0) { const struct nvkm_sclass *sclass;
oclass->base.oclass = NV_DEVICE;
oclass->base.minver = 0; switch (index) {
oclass->base.maxver = 0; case 0: sclass = &nvkm_udevice_sclass; break;
oclass->ctor = nvkm_client_child_new; default:
return 0;
}
return -EINVAL; return -EINVAL;
} }
oclass->ctor = nvkm_client_child_new;
oclass->base = *sclass;
return 0;
}
static const struct nvkm_object_func static const struct nvkm_object_func
nvkm_client_object_func = { nvkm_client_object_func = {
.mthd = nvkm_client_mthd, .mthd = nvkm_client_mthd,

View File

@ -1990,7 +1990,7 @@ nv_device(void *obj)
if (!nv_iclass(device, NV_SUBDEV_CLASS) && if (!nv_iclass(device, NV_SUBDEV_CLASS) &&
device->parent == &nvkm_client(device)->object) { device->parent == &nvkm_client(device)->object) {
struct { struct {
struct nvkm_parent base; struct nvkm_object base;
struct nvkm_device *device; struct nvkm_device *device;
} *udevice = (void *)device; } *udevice = (void *)device;
return udevice->device; return udevice->device;

View File

@ -21,6 +21,7 @@
* *
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#define nvkm_udevice(p) container_of((p), struct nvkm_udevice, object)
#include "priv.h" #include "priv.h"
#include <core/client.h> #include <core/client.h>
@ -28,19 +29,23 @@
#include <subdev/fb.h> #include <subdev/fb.h>
#include <subdev/instmem.h> #include <subdev/instmem.h>
#include <subdev/timer.h> #include <subdev/timer.h>
#include <engine/disp.h>
#include <engine/dmaobj.h>
#include <engine/fifo.h>
#include <engine/pm.h>
#include <nvif/class.h> #include <nvif/class.h>
#include <nvif/unpack.h> #include <nvif/unpack.h>
struct nvkm_udevice { struct nvkm_udevice {
struct nvkm_parent base; struct nvkm_object object;
struct nvkm_device *device; struct nvkm_device *device;
}; };
static int static int
nvkm_udevice_info(struct nvkm_object *object, void *data, u32 size) nvkm_udevice_info(struct nvkm_udevice *udev, void *data, u32 size)
{ {
struct nvkm_udevice *udev = (void *)object; struct nvkm_object *object = &udev->object;
struct nvkm_device *device = udev->device; struct nvkm_device *device = udev->device;
struct nvkm_fb *fb = device->fb; struct nvkm_fb *fb = device->fb;
struct nvkm_instmem *imem = device->imem; struct nvkm_instmem *imem = device->imem;
@ -114,9 +119,8 @@ nvkm_udevice_info(struct nvkm_object *object, void *data, u32 size)
} }
static int static int
nvkm_udevice_time(struct nvkm_object *object, void *data, u32 size) nvkm_udevice_time(struct nvkm_udevice *udev, void *data, u32 size)
{ {
struct nvkm_udevice *udev = (void *)object;
struct nvkm_device *device = udev->device; struct nvkm_device *device = udev->device;
struct nvkm_timer *tmr = device->timer; struct nvkm_timer *tmr = device->timer;
union { union {
@ -134,63 +138,70 @@ nvkm_udevice_time(struct nvkm_object *object, void *data, u32 size)
static int static int
nvkm_udevice_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) nvkm_udevice_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
{ {
struct nvkm_udevice *udev = nvkm_udevice(object);
switch (mthd) { switch (mthd) {
case NV_DEVICE_V0_INFO: case NV_DEVICE_V0_INFO:
return nvkm_udevice_info(object, data, size); return nvkm_udevice_info(udev, data, size);
case NV_DEVICE_V0_TIME: case NV_DEVICE_V0_TIME:
return nvkm_udevice_time(object, data, size); return nvkm_udevice_time(udev, data, size);
default: default:
break; break;
} }
return -EINVAL; return -EINVAL;
} }
static u8 static int
nvkm_udevice_rd08(struct nvkm_object *object, u64 addr) nvkm_udevice_rd08(struct nvkm_object *object, u64 addr, u8 *data)
{ {
struct nvkm_udevice *udev = (void *)object; struct nvkm_udevice *udev = nvkm_udevice(object);
return nvkm_rd08(udev->device, addr); *data = nvkm_rd08(udev->device, addr);
return 0;
} }
static u16 static int
nvkm_udevice_rd16(struct nvkm_object *object, u64 addr) nvkm_udevice_rd16(struct nvkm_object *object, u64 addr, u16 *data)
{ {
struct nvkm_udevice *udev = (void *)object; struct nvkm_udevice *udev = nvkm_udevice(object);
return nvkm_rd16(udev->device, addr); *data = nvkm_rd16(udev->device, addr);
return 0;
} }
static u32 static int
nvkm_udevice_rd32(struct nvkm_object *object, u64 addr) nvkm_udevice_rd32(struct nvkm_object *object, u64 addr, u32 *data)
{ {
struct nvkm_udevice *udev = (void *)object; struct nvkm_udevice *udev = nvkm_udevice(object);
return nvkm_rd32(udev->device, addr); *data = nvkm_rd32(udev->device, addr);
return 0;
} }
static void static int
nvkm_udevice_wr08(struct nvkm_object *object, u64 addr, u8 data) nvkm_udevice_wr08(struct nvkm_object *object, u64 addr, u8 data)
{ {
struct nvkm_udevice *udev = (void *)object; struct nvkm_udevice *udev = nvkm_udevice(object);
nvkm_wr08(udev->device, addr, data); nvkm_wr08(udev->device, addr, data);
return 0;
} }
static void static int
nvkm_udevice_wr16(struct nvkm_object *object, u64 addr, u16 data) nvkm_udevice_wr16(struct nvkm_object *object, u64 addr, u16 data)
{ {
struct nvkm_udevice *udev = (void *)object; struct nvkm_udevice *udev = nvkm_udevice(object);
nvkm_wr16(udev->device, addr, data); nvkm_wr16(udev->device, addr, data);
return 0;
} }
static void static int
nvkm_udevice_wr32(struct nvkm_object *object, u64 addr, u32 data) nvkm_udevice_wr32(struct nvkm_object *object, u64 addr, u32 data)
{ {
struct nvkm_udevice *udev = (void *)object; struct nvkm_udevice *udev = nvkm_udevice(object);
nvkm_wr32(udev->device, addr, data); nvkm_wr32(udev->device, addr, data);
return 0;
} }
static int static int
nvkm_udevice_map(struct nvkm_object *object, u64 *addr, u32 *size) nvkm_udevice_map(struct nvkm_object *object, u64 *addr, u32 *size)
{ {
struct nvkm_udevice *udev = (void *)object; struct nvkm_udevice *udev = nvkm_udevice(object);
struct nvkm_device *device = udev->device; struct nvkm_device *device = udev->device;
*addr = nv_device_resource_start(device, 0); *addr = nv_device_resource_start(device, 0);
*size = nv_device_resource_len(device, 0); *size = nv_device_resource_len(device, 0);
@ -200,7 +211,7 @@ nvkm_udevice_map(struct nvkm_object *object, u64 *addr, u32 *size)
static int static int
nvkm_udevice_fini(struct nvkm_object *object, bool suspend) nvkm_udevice_fini(struct nvkm_object *object, bool suspend)
{ {
struct nvkm_udevice *udev = (void *)object; struct nvkm_udevice *udev = nvkm_udevice(object);
struct nvkm_device *device = udev->device; struct nvkm_device *device = udev->device;
int ret = 0; int ret = 0;
@ -221,7 +232,7 @@ nvkm_udevice_fini(struct nvkm_object *object, bool suspend)
static int static int
nvkm_udevice_init(struct nvkm_object *object) nvkm_udevice_init(struct nvkm_object *object)
{ {
struct nvkm_udevice *udev = (void *)object; struct nvkm_udevice *udev = nvkm_udevice(object);
struct nvkm_device *device = udev->device; struct nvkm_device *device = udev->device;
int ret = 0; int ret = 0;
@ -239,11 +250,89 @@ nvkm_udevice_init(struct nvkm_object *object)
return ret; return ret;
} }
static struct nvkm_oclass static int
nvkm_udevice_oclass_super = { nvkm_udevice_child_old(const struct nvkm_oclass *oclass,
.handle = NV_DEVICE, void *data, u32 size, struct nvkm_object **pobject)
.ofuncs = &(struct nvkm_ofuncs) { {
.dtor = _nvkm_parent_dtor, struct nvkm_object *parent = oclass->parent;
struct nvkm_engine *engine = oclass->engine;
struct nvkm_oclass *eclass = (void *)oclass->priv;
struct nvkm_object *engctx = NULL;
int ret;
if (engine->cclass) {
ret = nvkm_object_old(parent, &engine->subdev.object,
engine->cclass, NULL, 0, &engctx);
if (ret)
return ret;
} else {
nvkm_object_ref(parent, &engctx);
}
ret = nvkm_object_old(engctx, &engine->subdev.object, eclass,
data, size, pobject);
nvkm_object_ref(NULL, &engctx);
return ret;
}
static int
nvkm_udevice_child_new(const struct nvkm_oclass *oclass,
void *data, u32 size, struct nvkm_object **pobject)
{
struct nvkm_udevice *udev = nvkm_udevice(oclass->parent);
const struct nvkm_oclass *sclass = oclass->priv;
return nvkm_object_old(&udev->object, NULL,
(struct nvkm_oclass *)sclass,
data, size, pobject);
}
static int
nvkm_udevice_child_get(struct nvkm_object *object, int index,
struct nvkm_oclass *oclass)
{
struct nvkm_udevice *udev = nvkm_udevice(object);
struct nvkm_device *device = udev->device;
struct nvkm_engine *engine;
u64 mask = (1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_FIFO) |
(1ULL << NVDEV_ENGINE_DISP) |
(1ULL << NVDEV_ENGINE_PM);
int i;
for (; i = __ffs64(mask), mask; mask &= ~(1ULL << i)) {
if ((engine = nvkm_device_engine(device, i))) {
struct nvkm_oclass *sclass = engine->sclass;
int c = 0;
while (sclass && sclass->ofuncs) {
if (c++ == index) {
oclass->base.oclass = sclass->handle;
oclass->base.minver = -2;
oclass->base.maxver = -2;
oclass->ctor = nvkm_udevice_child_old;
oclass->priv = sclass;
oclass->engine = engine;
return 0;
}
sclass++;
}
index -= c;
}
}
if (index == 0) {
oclass->ctor = nvkm_udevice_child_new;
oclass->base.oclass = nvkm_control_oclass[0].handle;
oclass->base.minver = -2;
oclass->base.maxver = -2;
oclass->priv = &nvkm_control_oclass[0];
return 0;
}
return -EINVAL;
}
static const struct nvkm_object_func
nvkm_udevice_super = {
.init = nvkm_udevice_init, .init = nvkm_udevice_init,
.fini = nvkm_udevice_fini, .fini = nvkm_udevice_fini,
.mthd = nvkm_udevice_mthd, .mthd = nvkm_udevice_mthd,
@ -254,19 +343,27 @@ nvkm_udevice_oclass_super = {
.wr08 = nvkm_udevice_wr08, .wr08 = nvkm_udevice_wr08,
.wr16 = nvkm_udevice_wr16, .wr16 = nvkm_udevice_wr16,
.wr32 = nvkm_udevice_wr32, .wr32 = nvkm_udevice_wr32,
} .sclass = nvkm_udevice_child_get,
}; };
static int static const struct nvkm_object_func
nvkm_udevice_ctor(struct nvkm_object *parent, struct nvkm_object *engine, nvkm_udevice = {
struct nvkm_oclass *oclass, void *data, u32 size, .init = nvkm_udevice_init,
.fini = nvkm_udevice_fini,
.mthd = nvkm_udevice_mthd,
.sclass = nvkm_udevice_child_get,
};
int
nvkm_udevice_new(const struct nvkm_oclass *oclass, void *data, u32 size,
struct nvkm_object **pobject) struct nvkm_object **pobject)
{ {
union { union {
struct nv_device_v0 v0; struct nv_device_v0 v0;
} *args = data; } *args = data;
struct nvkm_client *client = nvkm_client(parent); struct nvkm_client *client = oclass->client;
struct nvkm_device *device; struct nvkm_object *parent = &client->object;
const struct nvkm_object_func *func;
struct nvkm_udevice *udev; struct nvkm_udevice *udev;
int ret; int ret;
@ -279,34 +376,30 @@ nvkm_udevice_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
/* give priviledged clients register access */ /* give priviledged clients register access */
if (client->super) if (client->super)
oclass = &nvkm_udevice_oclass_super; func = &nvkm_udevice_super;
/* find the device subdev that matches what the client requested */
if (args->v0.device != ~0)
device = nvkm_device_find(args->v0.device);
else else
device = nvkm_device_find(client->device); func = &nvkm_udevice;
if (!device)
if (!(udev = kzalloc(sizeof(*udev), GFP_KERNEL)))
return -ENOMEM;
nvkm_object_ctor(func, oclass, &udev->object);
*pobject = &udev->object;
/* find the device that matches what the client requested */
if (args->v0.device != ~0)
udev->device = nvkm_device_find(args->v0.device);
else
udev->device = nvkm_device_find(client->device);
if (!udev->device)
return -ENODEV; return -ENODEV;
ret = nvkm_parent_create(parent, NULL, oclass, 0, nvkm_control_oclass,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_FIFO) |
(1ULL << NVDEV_ENGINE_DISP) |
(1ULL << NVDEV_ENGINE_PM), &udev);
*pobject = nv_object(udev);
if (ret)
return ret;
udev->device = device;
return 0; return 0;
} }
struct nvkm_ofuncs const struct nvkm_sclass
nvkm_udevice_ofuncs = { nvkm_udevice_sclass = {
.ctor = nvkm_udevice_ctor, .oclass = NV_DEVICE,
.dtor = _nvkm_parent_dtor, .minver = 0,
.init = nvkm_udevice_init, .maxver = 0,
.fini = nvkm_udevice_fini, .ctor = nvkm_udevice_new,
.mthd = nvkm_udevice_mthd,
}; };

View File

@ -1300,7 +1300,7 @@ nv50_disp_data_ctor(struct nvkm_object *parent,
int ret; int ret;
/* no context needed for channel objects... */ /* no context needed for channel objects... */
if (nv_mclass(parent) != NV_DEVICE) { if (parent->parent != &nvkm_client(parent)->object) {
atomic_inc(&parent->refcount); atomic_inc(&parent->refcount);
*pobject = parent; *pobject = parent;
return 1; return 1;

View File

@ -66,7 +66,7 @@ nvkm_dmaobj_bind(struct nvkm_dmaobj *dmaobj, struct nvkm_gpuobj *pargpu,
struct nvkm_object *parent = (void *)pargpu; struct nvkm_object *parent = (void *)pargpu;
struct hack *object; struct hack *object;
if (nv_mclass(parent->parent) == NV_DEVICE) { if (parent->parent->parent == &nvkm_client(parent)->object) {
/* delayed, or no, binding */ /* delayed, or no, binding */
return 0; return 0;
} }

View File

@ -656,7 +656,7 @@ nvkm_perfctx_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
int ret; int ret;
/* no context needed for perfdom objects... */ /* no context needed for perfdom objects... */
if (nv_mclass(parent) != NV_DEVICE) { if (parent->parent != &nvkm_client(parent)->object) {
atomic_inc(&parent->refcount); atomic_inc(&parent->refcount);
*pobject = parent; *pobject = parent;
return 1; return 1;