root/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c

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

DEFINITIONS

This source file includes following definitions.
  1. nvkm_udevice_info_subdev
  2. nvkm_udevice_info_v1
  3. nvkm_udevice_info
  4. nvkm_udevice_time
  5. nvkm_udevice_mthd
  6. nvkm_udevice_rd08
  7. nvkm_udevice_rd16
  8. nvkm_udevice_rd32
  9. nvkm_udevice_wr08
  10. nvkm_udevice_wr16
  11. nvkm_udevice_wr32
  12. nvkm_udevice_map
  13. nvkm_udevice_fini
  14. nvkm_udevice_init
  15. nvkm_udevice_child_new
  16. nvkm_udevice_child_get
  17. nvkm_udevice_new

   1 /*
   2  * Copyright 2012 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
  23  */
  24 #define nvkm_udevice(p) container_of((p), struct nvkm_udevice, object)
  25 #include "priv.h"
  26 #include "ctrl.h"
  27 
  28 #include <core/client.h>
  29 #include <subdev/fb.h>
  30 #include <subdev/instmem.h>
  31 #include <subdev/timer.h>
  32 
  33 #include <nvif/class.h>
  34 #include <nvif/cl0080.h>
  35 #include <nvif/unpack.h>
  36 
  37 struct nvkm_udevice {
  38         struct nvkm_object object;
  39         struct nvkm_device *device;
  40 };
  41 
  42 static int
  43 nvkm_udevice_info_subdev(struct nvkm_device *device, u64 mthd, u64 *data)
  44 {
  45         struct nvkm_subdev *subdev;
  46         enum nvkm_devidx subidx;
  47 
  48         switch (mthd & NV_DEVICE_INFO_UNIT) {
  49         case NV_DEVICE_FIFO(0): subidx = NVKM_ENGINE_FIFO; break;
  50         default:
  51                 return -EINVAL;
  52         }
  53 
  54         subdev = nvkm_device_subdev(device, subidx);
  55         if (subdev)
  56                 return nvkm_subdev_info(subdev, mthd, data);
  57         return -ENODEV;
  58 }
  59 
  60 static void
  61 nvkm_udevice_info_v1(struct nvkm_device *device,
  62                      struct nv_device_info_v1_data *args)
  63 {
  64         if (args->mthd & NV_DEVICE_INFO_UNIT) {
  65                 if (nvkm_udevice_info_subdev(device, args->mthd, &args->data))
  66                         args->mthd = NV_DEVICE_INFO_INVALID;
  67                 return;
  68         }
  69 
  70         switch (args->mthd) {
  71 #define ENGINE__(A,B,C) NV_DEVICE_INFO_ENGINE_##A: { int _i;                   \
  72         for (_i = (B), args->data = 0ULL; _i <= (C); _i++) {                   \
  73                 if (nvkm_device_engine(device, _i))                            \
  74                         args->data |= BIT_ULL(_i);                             \
  75         }                                                                      \
  76 }
  77 #define ENGINE_A(A) ENGINE__(A, NVKM_ENGINE_##A   , NVKM_ENGINE_##A)
  78 #define ENGINE_B(A) ENGINE__(A, NVKM_ENGINE_##A##0, NVKM_ENGINE_##A##_LAST)
  79         case ENGINE_A(SW    ); break;
  80         case ENGINE_A(GR    ); break;
  81         case ENGINE_A(MPEG  ); break;
  82         case ENGINE_A(ME    ); break;
  83         case ENGINE_A(CIPHER); break;
  84         case ENGINE_A(BSP   ); break;
  85         case ENGINE_A(VP    ); break;
  86         case ENGINE_B(CE    ); break;
  87         case ENGINE_A(SEC   ); break;
  88         case ENGINE_A(MSVLD ); break;
  89         case ENGINE_A(MSPDEC); break;
  90         case ENGINE_A(MSPPP ); break;
  91         case ENGINE_A(MSENC ); break;
  92         case ENGINE_A(VIC   ); break;
  93         case ENGINE_A(SEC2  ); break;
  94         case ENGINE_B(NVDEC ); break;
  95         case ENGINE_B(NVENC ); break;
  96         default:
  97                 args->mthd = NV_DEVICE_INFO_INVALID;
  98                 break;
  99         }
 100 }
 101 
 102 static int
 103 nvkm_udevice_info(struct nvkm_udevice *udev, void *data, u32 size)
 104 {
 105         struct nvkm_object *object = &udev->object;
 106         struct nvkm_device *device = udev->device;
 107         struct nvkm_fb *fb = device->fb;
 108         struct nvkm_instmem *imem = device->imem;
 109         union {
 110                 struct nv_device_info_v0 v0;
 111                 struct nv_device_info_v1 v1;
 112         } *args = data;
 113         int ret = -ENOSYS, i;
 114 
 115         nvif_ioctl(object, "device info size %d\n", size);
 116         if (!(ret = nvif_unpack(ret, &data, &size, args->v1, 1, 1, true))) {
 117                 nvif_ioctl(object, "device info vers %d count %d\n",
 118                            args->v1.version, args->v1.count);
 119                 if (args->v1.count * sizeof(args->v1.data[0]) == size) {
 120                         for (i = 0; i < args->v1.count; i++)
 121                                 nvkm_udevice_info_v1(device, &args->v1.data[i]);
 122                         return 0;
 123                 }
 124                 return -EINVAL;
 125         } else
 126         if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 127                 nvif_ioctl(object, "device info vers %d\n", args->v0.version);
 128         } else
 129                 return ret;
 130 
 131         switch (device->chipset) {
 132         case 0x01a:
 133         case 0x01f:
 134         case 0x04c:
 135         case 0x04e:
 136         case 0x063:
 137         case 0x067:
 138         case 0x068:
 139         case 0x0aa:
 140         case 0x0ac:
 141         case 0x0af:
 142                 args->v0.platform = NV_DEVICE_INFO_V0_IGP;
 143                 break;
 144         default:
 145                 switch (device->type) {
 146                 case NVKM_DEVICE_PCI:
 147                         args->v0.platform = NV_DEVICE_INFO_V0_PCI;
 148                         break;
 149                 case NVKM_DEVICE_AGP:
 150                         args->v0.platform = NV_DEVICE_INFO_V0_AGP;
 151                         break;
 152                 case NVKM_DEVICE_PCIE:
 153                         args->v0.platform = NV_DEVICE_INFO_V0_PCIE;
 154                         break;
 155                 case NVKM_DEVICE_TEGRA:
 156                         args->v0.platform = NV_DEVICE_INFO_V0_SOC;
 157                         break;
 158                 default:
 159                         WARN_ON(1);
 160                         break;
 161                 }
 162                 break;
 163         }
 164 
 165         switch (device->card_type) {
 166         case NV_04: args->v0.family = NV_DEVICE_INFO_V0_TNT; break;
 167         case NV_10:
 168         case NV_11: args->v0.family = NV_DEVICE_INFO_V0_CELSIUS; break;
 169         case NV_20: args->v0.family = NV_DEVICE_INFO_V0_KELVIN; break;
 170         case NV_30: args->v0.family = NV_DEVICE_INFO_V0_RANKINE; break;
 171         case NV_40: args->v0.family = NV_DEVICE_INFO_V0_CURIE; break;
 172         case NV_50: args->v0.family = NV_DEVICE_INFO_V0_TESLA; break;
 173         case NV_C0: args->v0.family = NV_DEVICE_INFO_V0_FERMI; break;
 174         case NV_E0: args->v0.family = NV_DEVICE_INFO_V0_KEPLER; break;
 175         case GM100: args->v0.family = NV_DEVICE_INFO_V0_MAXWELL; break;
 176         case GP100: args->v0.family = NV_DEVICE_INFO_V0_PASCAL; break;
 177         case GV100: args->v0.family = NV_DEVICE_INFO_V0_VOLTA; break;
 178         case TU100: args->v0.family = NV_DEVICE_INFO_V0_TURING; break;
 179         default:
 180                 args->v0.family = 0;
 181                 break;
 182         }
 183 
 184         args->v0.chipset  = device->chipset;
 185         args->v0.revision = device->chiprev;
 186         if (fb && fb->ram)
 187                 args->v0.ram_size = args->v0.ram_user = fb->ram->size;
 188         else
 189                 args->v0.ram_size = args->v0.ram_user = 0;
 190         if (imem && args->v0.ram_size > 0)
 191                 args->v0.ram_user = args->v0.ram_user - imem->reserved;
 192 
 193         strncpy(args->v0.chip, device->chip->name, sizeof(args->v0.chip));
 194         strncpy(args->v0.name, device->name, sizeof(args->v0.name));
 195         return 0;
 196 }
 197 
 198 static int
 199 nvkm_udevice_time(struct nvkm_udevice *udev, void *data, u32 size)
 200 {
 201         struct nvkm_object *object = &udev->object;
 202         struct nvkm_device *device = udev->device;
 203         union {
 204                 struct nv_device_time_v0 v0;
 205         } *args = data;
 206         int ret = -ENOSYS;
 207 
 208         nvif_ioctl(object, "device time size %d\n", size);
 209         if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 210                 nvif_ioctl(object, "device time vers %d\n", args->v0.version);
 211                 args->v0.time = nvkm_timer_read(device->timer);
 212         }
 213 
 214         return ret;
 215 }
 216 
 217 static int
 218 nvkm_udevice_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
 219 {
 220         struct nvkm_udevice *udev = nvkm_udevice(object);
 221         nvif_ioctl(object, "device mthd %08x\n", mthd);
 222         switch (mthd) {
 223         case NV_DEVICE_V0_INFO:
 224                 return nvkm_udevice_info(udev, data, size);
 225         case NV_DEVICE_V0_TIME:
 226                 return nvkm_udevice_time(udev, data, size);
 227         default:
 228                 break;
 229         }
 230         return -EINVAL;
 231 }
 232 
 233 static int
 234 nvkm_udevice_rd08(struct nvkm_object *object, u64 addr, u8 *data)
 235 {
 236         struct nvkm_udevice *udev = nvkm_udevice(object);
 237         *data = nvkm_rd08(udev->device, addr);
 238         return 0;
 239 }
 240 
 241 static int
 242 nvkm_udevice_rd16(struct nvkm_object *object, u64 addr, u16 *data)
 243 {
 244         struct nvkm_udevice *udev = nvkm_udevice(object);
 245         *data = nvkm_rd16(udev->device, addr);
 246         return 0;
 247 }
 248 
 249 static int
 250 nvkm_udevice_rd32(struct nvkm_object *object, u64 addr, u32 *data)
 251 {
 252         struct nvkm_udevice *udev = nvkm_udevice(object);
 253         *data = nvkm_rd32(udev->device, addr);
 254         return 0;
 255 }
 256 
 257 static int
 258 nvkm_udevice_wr08(struct nvkm_object *object, u64 addr, u8 data)
 259 {
 260         struct nvkm_udevice *udev = nvkm_udevice(object);
 261         nvkm_wr08(udev->device, addr, data);
 262         return 0;
 263 }
 264 
 265 static int
 266 nvkm_udevice_wr16(struct nvkm_object *object, u64 addr, u16 data)
 267 {
 268         struct nvkm_udevice *udev = nvkm_udevice(object);
 269         nvkm_wr16(udev->device, addr, data);
 270         return 0;
 271 }
 272 
 273 static int
 274 nvkm_udevice_wr32(struct nvkm_object *object, u64 addr, u32 data)
 275 {
 276         struct nvkm_udevice *udev = nvkm_udevice(object);
 277         nvkm_wr32(udev->device, addr, data);
 278         return 0;
 279 }
 280 
 281 static int
 282 nvkm_udevice_map(struct nvkm_object *object, void *argv, u32 argc,
 283                  enum nvkm_object_map *type, u64 *addr, u64 *size)
 284 {
 285         struct nvkm_udevice *udev = nvkm_udevice(object);
 286         struct nvkm_device *device = udev->device;
 287         *type = NVKM_OBJECT_MAP_IO;
 288         *addr = device->func->resource_addr(device, 0);
 289         *size = device->func->resource_size(device, 0);
 290         return 0;
 291 }
 292 
 293 static int
 294 nvkm_udevice_fini(struct nvkm_object *object, bool suspend)
 295 {
 296         struct nvkm_udevice *udev = nvkm_udevice(object);
 297         struct nvkm_device *device = udev->device;
 298         int ret = 0;
 299 
 300         mutex_lock(&device->mutex);
 301         if (!--device->refcount) {
 302                 ret = nvkm_device_fini(device, suspend);
 303                 if (ret && suspend) {
 304                         device->refcount++;
 305                         goto done;
 306                 }
 307         }
 308 
 309 done:
 310         mutex_unlock(&device->mutex);
 311         return ret;
 312 }
 313 
 314 static int
 315 nvkm_udevice_init(struct nvkm_object *object)
 316 {
 317         struct nvkm_udevice *udev = nvkm_udevice(object);
 318         struct nvkm_device *device = udev->device;
 319         int ret = 0;
 320 
 321         mutex_lock(&device->mutex);
 322         if (!device->refcount++) {
 323                 ret = nvkm_device_init(device);
 324                 if (ret) {
 325                         device->refcount--;
 326                         goto done;
 327                 }
 328         }
 329 
 330 done:
 331         mutex_unlock(&device->mutex);
 332         return ret;
 333 }
 334 
 335 static int
 336 nvkm_udevice_child_new(const struct nvkm_oclass *oclass,
 337                        void *data, u32 size, struct nvkm_object **pobject)
 338 {
 339         struct nvkm_udevice *udev = nvkm_udevice(oclass->parent);
 340         const struct nvkm_device_oclass *sclass = oclass->priv;
 341         return sclass->ctor(udev->device, oclass, data, size, pobject);
 342 }
 343 
 344 static int
 345 nvkm_udevice_child_get(struct nvkm_object *object, int index,
 346                        struct nvkm_oclass *oclass)
 347 {
 348         struct nvkm_udevice *udev = nvkm_udevice(object);
 349         struct nvkm_device *device = udev->device;
 350         struct nvkm_engine *engine;
 351         u64 mask = (1ULL << NVKM_ENGINE_DMAOBJ) |
 352                    (1ULL << NVKM_ENGINE_FIFO) |
 353                    (1ULL << NVKM_ENGINE_DISP) |
 354                    (1ULL << NVKM_ENGINE_PM);
 355         const struct nvkm_device_oclass *sclass = NULL;
 356         int i;
 357 
 358         for (; i = __ffs64(mask), mask && !sclass; mask &= ~(1ULL << i)) {
 359                 if (!(engine = nvkm_device_engine(device, i)) ||
 360                     !(engine->func->base.sclass))
 361                         continue;
 362                 oclass->engine = engine;
 363 
 364                 index -= engine->func->base.sclass(oclass, index, &sclass);
 365         }
 366 
 367         if (!sclass) {
 368                 if (index-- == 0)
 369                         sclass = &nvkm_control_oclass;
 370                 else if (device->mmu && index-- == 0)
 371                         sclass = &device->mmu->user;
 372                 else if (device->fault && index-- == 0)
 373                         sclass = &device->fault->user;
 374                 else
 375                         return -EINVAL;
 376 
 377                 oclass->base = sclass->base;
 378         }
 379 
 380         oclass->ctor = nvkm_udevice_child_new;
 381         oclass->priv = sclass;
 382         return 0;
 383 }
 384 
 385 static const struct nvkm_object_func
 386 nvkm_udevice_super = {
 387         .init = nvkm_udevice_init,
 388         .fini = nvkm_udevice_fini,
 389         .mthd = nvkm_udevice_mthd,
 390         .map = nvkm_udevice_map,
 391         .rd08 = nvkm_udevice_rd08,
 392         .rd16 = nvkm_udevice_rd16,
 393         .rd32 = nvkm_udevice_rd32,
 394         .wr08 = nvkm_udevice_wr08,
 395         .wr16 = nvkm_udevice_wr16,
 396         .wr32 = nvkm_udevice_wr32,
 397         .sclass = nvkm_udevice_child_get,
 398 };
 399 
 400 static const struct nvkm_object_func
 401 nvkm_udevice = {
 402         .init = nvkm_udevice_init,
 403         .fini = nvkm_udevice_fini,
 404         .mthd = nvkm_udevice_mthd,
 405         .sclass = nvkm_udevice_child_get,
 406 };
 407 
 408 static int
 409 nvkm_udevice_new(const struct nvkm_oclass *oclass, void *data, u32 size,
 410                  struct nvkm_object **pobject)
 411 {
 412         union {
 413                 struct nv_device_v0 v0;
 414         } *args = data;
 415         struct nvkm_client *client = oclass->client;
 416         struct nvkm_object *parent = &client->object;
 417         const struct nvkm_object_func *func;
 418         struct nvkm_udevice *udev;
 419         int ret = -ENOSYS;
 420 
 421         nvif_ioctl(parent, "create device size %d\n", size);
 422         if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 423                 nvif_ioctl(parent, "create device v%d device %016llx\n",
 424                            args->v0.version, args->v0.device);
 425         } else
 426                 return ret;
 427 
 428         /* give priviledged clients register access */
 429         if (client->super)
 430                 func = &nvkm_udevice_super;
 431         else
 432                 func = &nvkm_udevice;
 433 
 434         if (!(udev = kzalloc(sizeof(*udev), GFP_KERNEL)))
 435                 return -ENOMEM;
 436         nvkm_object_ctor(func, oclass, &udev->object);
 437         *pobject = &udev->object;
 438 
 439         /* find the device that matches what the client requested */
 440         if (args->v0.device != ~0)
 441                 udev->device = nvkm_device_find(args->v0.device);
 442         else
 443                 udev->device = nvkm_device_find(client->device);
 444         if (!udev->device)
 445                 return -ENODEV;
 446 
 447         return 0;
 448 }
 449 
 450 const struct nvkm_sclass
 451 nvkm_udevice_sclass = {
 452         .oclass = NV_DEVICE,
 453         .minver = 0,
 454         .maxver = 0,
 455         .ctor = nvkm_udevice_new,
 456 };

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