0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include <nvif/object.h>
0026 #include <nvif/client.h>
0027 #include <nvif/driver.h>
0028 #include <nvif/ioctl.h>
0029
0030 int
0031 nvif_object_ioctl(struct nvif_object *object, void *data, u32 size, void **hack)
0032 {
0033 struct nvif_client *client = object->client;
0034 union {
0035 struct nvif_ioctl_v0 v0;
0036 } *args = data;
0037
0038 if (size >= sizeof(*args) && args->v0.version == 0) {
0039 if (object != &client->object)
0040 args->v0.object = nvif_handle(object);
0041 else
0042 args->v0.object = 0;
0043 args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY;
0044 } else
0045 return -ENOSYS;
0046
0047 return client->driver->ioctl(client->object.priv, data, size, hack);
0048 }
0049
0050 void
0051 nvif_object_sclass_put(struct nvif_sclass **psclass)
0052 {
0053 kfree(*psclass);
0054 *psclass = NULL;
0055 }
0056
0057 int
0058 nvif_object_sclass_get(struct nvif_object *object, struct nvif_sclass **psclass)
0059 {
0060 struct {
0061 struct nvif_ioctl_v0 ioctl;
0062 struct nvif_ioctl_sclass_v0 sclass;
0063 } *args = NULL;
0064 int ret, cnt = 0, i;
0065 u32 size;
0066
0067 while (1) {
0068 size = sizeof(*args) + cnt * sizeof(args->sclass.oclass[0]);
0069 if (!(args = kmalloc(size, GFP_KERNEL)))
0070 return -ENOMEM;
0071 args->ioctl.version = 0;
0072 args->ioctl.type = NVIF_IOCTL_V0_SCLASS;
0073 args->sclass.version = 0;
0074 args->sclass.count = cnt;
0075
0076 ret = nvif_object_ioctl(object, args, size, NULL);
0077 if (ret == 0 && args->sclass.count <= cnt)
0078 break;
0079 cnt = args->sclass.count;
0080 kfree(args);
0081 if (ret != 0)
0082 return ret;
0083 }
0084
0085 *psclass = kcalloc(args->sclass.count, sizeof(**psclass), GFP_KERNEL);
0086 if (*psclass) {
0087 for (i = 0; i < args->sclass.count; i++) {
0088 (*psclass)[i].oclass = args->sclass.oclass[i].oclass;
0089 (*psclass)[i].minver = args->sclass.oclass[i].minver;
0090 (*psclass)[i].maxver = args->sclass.oclass[i].maxver;
0091 }
0092 ret = args->sclass.count;
0093 } else {
0094 ret = -ENOMEM;
0095 }
0096
0097 kfree(args);
0098 return ret;
0099 }
0100
0101 u32
0102 nvif_object_rd(struct nvif_object *object, int size, u64 addr)
0103 {
0104 struct {
0105 struct nvif_ioctl_v0 ioctl;
0106 struct nvif_ioctl_rd_v0 rd;
0107 } args = {
0108 .ioctl.type = NVIF_IOCTL_V0_RD,
0109 .rd.size = size,
0110 .rd.addr = addr,
0111 };
0112 int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
0113 if (ret) {
0114
0115 return 0;
0116 }
0117 return args.rd.data;
0118 }
0119
0120 void
0121 nvif_object_wr(struct nvif_object *object, int size, u64 addr, u32 data)
0122 {
0123 struct {
0124 struct nvif_ioctl_v0 ioctl;
0125 struct nvif_ioctl_wr_v0 wr;
0126 } args = {
0127 .ioctl.type = NVIF_IOCTL_V0_WR,
0128 .wr.size = size,
0129 .wr.addr = addr,
0130 .wr.data = data,
0131 };
0132 int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
0133 if (ret) {
0134
0135 }
0136 }
0137
0138 int
0139 nvif_object_mthd(struct nvif_object *object, u32 mthd, void *data, u32 size)
0140 {
0141 struct {
0142 struct nvif_ioctl_v0 ioctl;
0143 struct nvif_ioctl_mthd_v0 mthd;
0144 } *args;
0145 u8 stack[128];
0146 int ret;
0147
0148 if (sizeof(*args) + size > sizeof(stack)) {
0149 if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
0150 return -ENOMEM;
0151 } else {
0152 args = (void *)stack;
0153 }
0154 args->ioctl.version = 0;
0155 args->ioctl.type = NVIF_IOCTL_V0_MTHD;
0156 args->mthd.version = 0;
0157 args->mthd.method = mthd;
0158
0159 memcpy(args->mthd.data, data, size);
0160 ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
0161 memcpy(data, args->mthd.data, size);
0162 if (args != (void *)stack)
0163 kfree(args);
0164 return ret;
0165 }
0166
0167 void
0168 nvif_object_unmap_handle(struct nvif_object *object)
0169 {
0170 struct {
0171 struct nvif_ioctl_v0 ioctl;
0172 struct nvif_ioctl_unmap unmap;
0173 } args = {
0174 .ioctl.type = NVIF_IOCTL_V0_UNMAP,
0175 };
0176
0177 nvif_object_ioctl(object, &args, sizeof(args), NULL);
0178 }
0179
0180 int
0181 nvif_object_map_handle(struct nvif_object *object, void *argv, u32 argc,
0182 u64 *handle, u64 *length)
0183 {
0184 struct {
0185 struct nvif_ioctl_v0 ioctl;
0186 struct nvif_ioctl_map_v0 map;
0187 } *args;
0188 u32 argn = sizeof(*args) + argc;
0189 int ret, maptype;
0190
0191 if (!(args = kzalloc(argn, GFP_KERNEL)))
0192 return -ENOMEM;
0193 args->ioctl.type = NVIF_IOCTL_V0_MAP;
0194 memcpy(args->map.data, argv, argc);
0195
0196 ret = nvif_object_ioctl(object, args, argn, NULL);
0197 *handle = args->map.handle;
0198 *length = args->map.length;
0199 maptype = args->map.type;
0200 kfree(args);
0201 return ret ? ret : (maptype == NVIF_IOCTL_MAP_V0_IO);
0202 }
0203
0204 void
0205 nvif_object_unmap(struct nvif_object *object)
0206 {
0207 struct nvif_client *client = object->client;
0208 if (object->map.ptr) {
0209 if (object->map.size) {
0210 client->driver->unmap(client, object->map.ptr,
0211 object->map.size);
0212 object->map.size = 0;
0213 }
0214 object->map.ptr = NULL;
0215 nvif_object_unmap_handle(object);
0216 }
0217 }
0218
0219 int
0220 nvif_object_map(struct nvif_object *object, void *argv, u32 argc)
0221 {
0222 struct nvif_client *client = object->client;
0223 u64 handle, length;
0224 int ret = nvif_object_map_handle(object, argv, argc, &handle, &length);
0225 if (ret >= 0) {
0226 if (ret) {
0227 object->map.ptr = client->driver->map(client,
0228 handle,
0229 length);
0230 if (ret = -ENOMEM, object->map.ptr) {
0231 object->map.size = length;
0232 return 0;
0233 }
0234 } else {
0235 object->map.ptr = (void *)(unsigned long)handle;
0236 return 0;
0237 }
0238 nvif_object_unmap_handle(object);
0239 }
0240 return ret;
0241 }
0242
0243 void
0244 nvif_object_dtor(struct nvif_object *object)
0245 {
0246 struct {
0247 struct nvif_ioctl_v0 ioctl;
0248 struct nvif_ioctl_del del;
0249 } args = {
0250 .ioctl.type = NVIF_IOCTL_V0_DEL,
0251 };
0252
0253 if (!nvif_object_constructed(object))
0254 return;
0255
0256 nvif_object_unmap(object);
0257 nvif_object_ioctl(object, &args, sizeof(args), NULL);
0258 object->client = NULL;
0259 }
0260
0261 int
0262 nvif_object_ctor(struct nvif_object *parent, const char *name, u32 handle,
0263 s32 oclass, void *data, u32 size, struct nvif_object *object)
0264 {
0265 struct {
0266 struct nvif_ioctl_v0 ioctl;
0267 struct nvif_ioctl_new_v0 new;
0268 } *args;
0269 int ret = 0;
0270
0271 object->client = NULL;
0272 object->name = name ? name : "nvifObject";
0273 object->handle = handle;
0274 object->oclass = oclass;
0275 object->map.ptr = NULL;
0276 object->map.size = 0;
0277
0278 if (parent) {
0279 if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL))) {
0280 nvif_object_dtor(object);
0281 return -ENOMEM;
0282 }
0283
0284 object->parent = parent->parent;
0285
0286 args->ioctl.version = 0;
0287 args->ioctl.type = NVIF_IOCTL_V0_NEW;
0288 args->new.version = 0;
0289 args->new.route = parent->client->route;
0290 args->new.token = nvif_handle(object);
0291 args->new.object = nvif_handle(object);
0292 args->new.handle = handle;
0293 args->new.oclass = oclass;
0294
0295 memcpy(args->new.data, data, size);
0296 ret = nvif_object_ioctl(parent, args, sizeof(*args) + size,
0297 &object->priv);
0298 memcpy(data, args->new.data, size);
0299 kfree(args);
0300 if (ret == 0)
0301 object->client = parent->client;
0302 }
0303
0304 if (ret)
0305 nvif_object_dtor(object);
0306 return ret;
0307 }