root/drivers/gpu/drm/nouveau/nvif/object.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nvif_object_ioctl
  2. nvif_object_sclass_put
  3. nvif_object_sclass_get
  4. nvif_object_rd
  5. nvif_object_wr
  6. nvif_object_mthd
  7. nvif_object_unmap_handle
  8. nvif_object_map_handle
  9. nvif_object_unmap
  10. nvif_object_map
  11. nvif_object_fini
  12. nvif_object_init

   1 /*
   2  * Copyright 2014 Red Hat Inc.
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice shall be included in
  12  * all copies or substantial portions of the Software.
  13  *
  14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20  * OTHER DEALINGS IN THE SOFTWARE.
  21  *
  22  * Authors: Ben Skeggs <bskeggs@redhat.com>
  23  */
  24 
  25 #include <nvif/object.h>
  26 #include <nvif/client.h>
  27 #include <nvif/driver.h>
  28 #include <nvif/ioctl.h>
  29 
  30 int
  31 nvif_object_ioctl(struct nvif_object *object, void *data, u32 size, void **hack)
  32 {
  33         struct nvif_client *client = object->client;
  34         union {
  35                 struct nvif_ioctl_v0 v0;
  36         } *args = data;
  37 
  38         if (size >= sizeof(*args) && args->v0.version == 0) {
  39                 if (object != &client->object)
  40                         args->v0.object = nvif_handle(object);
  41                 else
  42                         args->v0.object = 0;
  43                 args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY;
  44         } else
  45                 return -ENOSYS;
  46 
  47         return client->driver->ioctl(client->object.priv, client->super,
  48                                      data, size, hack);
  49 }
  50 
  51 void
  52 nvif_object_sclass_put(struct nvif_sclass **psclass)
  53 {
  54         kfree(*psclass);
  55         *psclass = NULL;
  56 }
  57 
  58 int
  59 nvif_object_sclass_get(struct nvif_object *object, struct nvif_sclass **psclass)
  60 {
  61         struct {
  62                 struct nvif_ioctl_v0 ioctl;
  63                 struct nvif_ioctl_sclass_v0 sclass;
  64         } *args = NULL;
  65         int ret, cnt = 0, i;
  66         u32 size;
  67 
  68         while (1) {
  69                 size = sizeof(*args) + cnt * sizeof(args->sclass.oclass[0]);
  70                 if (!(args = kmalloc(size, GFP_KERNEL)))
  71                         return -ENOMEM;
  72                 args->ioctl.version = 0;
  73                 args->ioctl.type = NVIF_IOCTL_V0_SCLASS;
  74                 args->sclass.version = 0;
  75                 args->sclass.count = cnt;
  76 
  77                 ret = nvif_object_ioctl(object, args, size, NULL);
  78                 if (ret == 0 && args->sclass.count <= cnt)
  79                         break;
  80                 cnt = args->sclass.count;
  81                 kfree(args);
  82                 if (ret != 0)
  83                         return ret;
  84         }
  85 
  86         *psclass = kcalloc(args->sclass.count, sizeof(**psclass), GFP_KERNEL);
  87         if (*psclass) {
  88                 for (i = 0; i < args->sclass.count; i++) {
  89                         (*psclass)[i].oclass = args->sclass.oclass[i].oclass;
  90                         (*psclass)[i].minver = args->sclass.oclass[i].minver;
  91                         (*psclass)[i].maxver = args->sclass.oclass[i].maxver;
  92                 }
  93                 ret = args->sclass.count;
  94         } else {
  95                 ret = -ENOMEM;
  96         }
  97 
  98         kfree(args);
  99         return ret;
 100 }
 101 
 102 u32
 103 nvif_object_rd(struct nvif_object *object, int size, u64 addr)
 104 {
 105         struct {
 106                 struct nvif_ioctl_v0 ioctl;
 107                 struct nvif_ioctl_rd_v0 rd;
 108         } args = {
 109                 .ioctl.type = NVIF_IOCTL_V0_RD,
 110                 .rd.size = size,
 111                 .rd.addr = addr,
 112         };
 113         int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
 114         if (ret) {
 115                 /*XXX: warn? */
 116                 return 0;
 117         }
 118         return args.rd.data;
 119 }
 120 
 121 void
 122 nvif_object_wr(struct nvif_object *object, int size, u64 addr, u32 data)
 123 {
 124         struct {
 125                 struct nvif_ioctl_v0 ioctl;
 126                 struct nvif_ioctl_wr_v0 wr;
 127         } args = {
 128                 .ioctl.type = NVIF_IOCTL_V0_WR,
 129                 .wr.size = size,
 130                 .wr.addr = addr,
 131                 .wr.data = data,
 132         };
 133         int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
 134         if (ret) {
 135                 /*XXX: warn? */
 136         }
 137 }
 138 
 139 int
 140 nvif_object_mthd(struct nvif_object *object, u32 mthd, void *data, u32 size)
 141 {
 142         struct {
 143                 struct nvif_ioctl_v0 ioctl;
 144                 struct nvif_ioctl_mthd_v0 mthd;
 145         } *args;
 146         u8 stack[128];
 147         int ret;
 148 
 149         if (sizeof(*args) + size > sizeof(stack)) {
 150                 if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
 151                         return -ENOMEM;
 152         } else {
 153                 args = (void *)stack;
 154         }
 155         args->ioctl.version = 0;
 156         args->ioctl.type = NVIF_IOCTL_V0_MTHD;
 157         args->mthd.version = 0;
 158         args->mthd.method = mthd;
 159 
 160         memcpy(args->mthd.data, data, size);
 161         ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
 162         memcpy(data, args->mthd.data, size);
 163         if (args != (void *)stack)
 164                 kfree(args);
 165         return ret;
 166 }
 167 
 168 void
 169 nvif_object_unmap_handle(struct nvif_object *object)
 170 {
 171         struct {
 172                 struct nvif_ioctl_v0 ioctl;
 173                 struct nvif_ioctl_unmap unmap;
 174         } args = {
 175                 .ioctl.type = NVIF_IOCTL_V0_UNMAP,
 176         };
 177 
 178         nvif_object_ioctl(object, &args, sizeof(args), NULL);
 179 }
 180 
 181 int
 182 nvif_object_map_handle(struct nvif_object *object, void *argv, u32 argc,
 183                        u64 *handle, u64 *length)
 184 {
 185         struct {
 186                 struct nvif_ioctl_v0 ioctl;
 187                 struct nvif_ioctl_map_v0 map;
 188         } *args;
 189         u32 argn = sizeof(*args) + argc;
 190         int ret, maptype;
 191 
 192         if (!(args = kzalloc(argn, GFP_KERNEL)))
 193                 return -ENOMEM;
 194         args->ioctl.type = NVIF_IOCTL_V0_MAP;
 195         memcpy(args->map.data, argv, argc);
 196 
 197         ret = nvif_object_ioctl(object, args, argn, NULL);
 198         *handle = args->map.handle;
 199         *length = args->map.length;
 200         maptype = args->map.type;
 201         kfree(args);
 202         return ret ? ret : (maptype == NVIF_IOCTL_MAP_V0_IO);
 203 }
 204 
 205 void
 206 nvif_object_unmap(struct nvif_object *object)
 207 {
 208         struct nvif_client *client = object->client;
 209         if (object->map.ptr) {
 210                 if (object->map.size) {
 211                         client->driver->unmap(client, object->map.ptr,
 212                                                       object->map.size);
 213                         object->map.size = 0;
 214                 }
 215                 object->map.ptr = NULL;
 216                 nvif_object_unmap_handle(object);
 217         }
 218 }
 219 
 220 int
 221 nvif_object_map(struct nvif_object *object, void *argv, u32 argc)
 222 {
 223         struct nvif_client *client = object->client;
 224         u64 handle, length;
 225         int ret = nvif_object_map_handle(object, argv, argc, &handle, &length);
 226         if (ret >= 0) {
 227                 if (ret) {
 228                         object->map.ptr = client->driver->map(client,
 229                                                               handle,
 230                                                               length);
 231                         if (ret = -ENOMEM, object->map.ptr) {
 232                                 object->map.size = length;
 233                                 return 0;
 234                         }
 235                 } else {
 236                         object->map.ptr = (void *)(unsigned long)handle;
 237                         return 0;
 238                 }
 239                 nvif_object_unmap_handle(object);
 240         }
 241         return ret;
 242 }
 243 
 244 void
 245 nvif_object_fini(struct nvif_object *object)
 246 {
 247         struct {
 248                 struct nvif_ioctl_v0 ioctl;
 249                 struct nvif_ioctl_del del;
 250         } args = {
 251                 .ioctl.type = NVIF_IOCTL_V0_DEL,
 252         };
 253 
 254         if (!object->client)
 255                 return;
 256 
 257         nvif_object_unmap(object);
 258         nvif_object_ioctl(object, &args, sizeof(args), NULL);
 259         object->client = NULL;
 260 }
 261 
 262 int
 263 nvif_object_init(struct nvif_object *parent, u32 handle, s32 oclass,
 264                  void *data, u32 size, struct nvif_object *object)
 265 {
 266         struct {
 267                 struct nvif_ioctl_v0 ioctl;
 268                 struct nvif_ioctl_new_v0 new;
 269         } *args;
 270         int ret = 0;
 271 
 272         object->client = NULL;
 273         object->handle = handle;
 274         object->oclass = oclass;
 275         object->map.ptr = NULL;
 276         object->map.size = 0;
 277 
 278         if (parent) {
 279                 if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL))) {
 280                         nvif_object_fini(object);
 281                         return -ENOMEM;
 282                 }
 283 
 284                 args->ioctl.version = 0;
 285                 args->ioctl.type = NVIF_IOCTL_V0_NEW;
 286                 args->new.version = 0;
 287                 args->new.route = parent->client->route;
 288                 args->new.token = nvif_handle(object);
 289                 args->new.object = nvif_handle(object);
 290                 args->new.handle = handle;
 291                 args->new.oclass = oclass;
 292 
 293                 memcpy(args->new.data, data, size);
 294                 ret = nvif_object_ioctl(parent, args, sizeof(*args) + size,
 295                                         &object->priv);
 296                 memcpy(data, args->new.data, size);
 297                 kfree(args);
 298                 if (ret == 0)
 299                         object->client = parent->client;
 300         }
 301 
 302         if (ret)
 303                 nvif_object_fini(object);
 304         return ret;
 305 }

/* [<][>][^][v][top][bottom][index][help] */