linux/drivers/gpu/drm/nouveau/nvkm/core/subdev.c
<<
>>
Prefs
   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#include <core/subdev.h>
  25#include <core/device.h>
  26#include <core/option.h>
  27#include <subdev/mc.h>
  28
  29static struct lock_class_key nvkm_subdev_lock_class[NVKM_SUBDEV_NR];
  30
  31const char *
  32nvkm_subdev_name[NVKM_SUBDEV_NR] = {
  33        [NVKM_SUBDEV_BAR     ] = "bar",
  34        [NVKM_SUBDEV_VBIOS   ] = "bios",
  35        [NVKM_SUBDEV_BUS     ] = "bus",
  36        [NVKM_SUBDEV_CLK     ] = "clk",
  37        [NVKM_SUBDEV_DEVINIT ] = "devinit",
  38        [NVKM_SUBDEV_FAULT   ] = "fault",
  39        [NVKM_SUBDEV_FB      ] = "fb",
  40        [NVKM_SUBDEV_FUSE    ] = "fuse",
  41        [NVKM_SUBDEV_GPIO    ] = "gpio",
  42        [NVKM_SUBDEV_GSP     ] = "gsp",
  43        [NVKM_SUBDEV_I2C     ] = "i2c",
  44        [NVKM_SUBDEV_IBUS    ] = "priv",
  45        [NVKM_SUBDEV_ICCSENSE] = "iccsense",
  46        [NVKM_SUBDEV_INSTMEM ] = "imem",
  47        [NVKM_SUBDEV_LTC     ] = "ltc",
  48        [NVKM_SUBDEV_MC      ] = "mc",
  49        [NVKM_SUBDEV_MMU     ] = "mmu",
  50        [NVKM_SUBDEV_MXM     ] = "mxm",
  51        [NVKM_SUBDEV_PCI     ] = "pci",
  52        [NVKM_SUBDEV_PMU     ] = "pmu",
  53        [NVKM_SUBDEV_SECBOOT ] = "secboot",
  54        [NVKM_SUBDEV_THERM   ] = "therm",
  55        [NVKM_SUBDEV_TIMER   ] = "tmr",
  56        [NVKM_SUBDEV_TOP     ] = "top",
  57        [NVKM_SUBDEV_VOLT    ] = "volt",
  58        [NVKM_ENGINE_BSP     ] = "bsp",
  59        [NVKM_ENGINE_CE0     ] = "ce0",
  60        [NVKM_ENGINE_CE1     ] = "ce1",
  61        [NVKM_ENGINE_CE2     ] = "ce2",
  62        [NVKM_ENGINE_CE3     ] = "ce3",
  63        [NVKM_ENGINE_CE4     ] = "ce4",
  64        [NVKM_ENGINE_CE5     ] = "ce5",
  65        [NVKM_ENGINE_CE6     ] = "ce6",
  66        [NVKM_ENGINE_CE7     ] = "ce7",
  67        [NVKM_ENGINE_CE8     ] = "ce8",
  68        [NVKM_ENGINE_CIPHER  ] = "cipher",
  69        [NVKM_ENGINE_DISP    ] = "disp",
  70        [NVKM_ENGINE_DMAOBJ  ] = "dma",
  71        [NVKM_ENGINE_FIFO    ] = "fifo",
  72        [NVKM_ENGINE_GR      ] = "gr",
  73        [NVKM_ENGINE_IFB     ] = "ifb",
  74        [NVKM_ENGINE_ME      ] = "me",
  75        [NVKM_ENGINE_MPEG    ] = "mpeg",
  76        [NVKM_ENGINE_MSENC   ] = "msenc",
  77        [NVKM_ENGINE_MSPDEC  ] = "mspdec",
  78        [NVKM_ENGINE_MSPPP   ] = "msppp",
  79        [NVKM_ENGINE_MSVLD   ] = "msvld",
  80        [NVKM_ENGINE_NVENC0  ] = "nvenc0",
  81        [NVKM_ENGINE_NVENC1  ] = "nvenc1",
  82        [NVKM_ENGINE_NVENC2  ] = "nvenc2",
  83        [NVKM_ENGINE_NVDEC0  ] = "nvdec0",
  84        [NVKM_ENGINE_NVDEC1  ] = "nvdec1",
  85        [NVKM_ENGINE_NVDEC2  ] = "nvdec2",
  86        [NVKM_ENGINE_PM      ] = "pm",
  87        [NVKM_ENGINE_SEC     ] = "sec",
  88        [NVKM_ENGINE_SEC2    ] = "sec2",
  89        [NVKM_ENGINE_SW      ] = "sw",
  90        [NVKM_ENGINE_VIC     ] = "vic",
  91        [NVKM_ENGINE_VP      ] = "vp",
  92};
  93
  94void
  95nvkm_subdev_intr(struct nvkm_subdev *subdev)
  96{
  97        if (subdev->func->intr)
  98                subdev->func->intr(subdev);
  99}
 100
 101int
 102nvkm_subdev_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data)
 103{
 104        if (subdev->func->info)
 105                return subdev->func->info(subdev, mthd, data);
 106        return -ENOSYS;
 107}
 108
 109int
 110nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
 111{
 112        struct nvkm_device *device = subdev->device;
 113        const char *action = suspend ? "suspend" : "fini";
 114        s64 time;
 115
 116        nvkm_trace(subdev, "%s running...\n", action);
 117        time = ktime_to_us(ktime_get());
 118
 119        if (subdev->func->fini) {
 120                int ret = subdev->func->fini(subdev, suspend);
 121                if (ret) {
 122                        nvkm_error(subdev, "%s failed, %d\n", action, ret);
 123                        if (suspend)
 124                                return ret;
 125                }
 126        }
 127
 128        nvkm_mc_reset(device, subdev->index);
 129
 130        time = ktime_to_us(ktime_get()) - time;
 131        nvkm_trace(subdev, "%s completed in %lldus\n", action, time);
 132        return 0;
 133}
 134
 135int
 136nvkm_subdev_preinit(struct nvkm_subdev *subdev)
 137{
 138        s64 time;
 139
 140        nvkm_trace(subdev, "preinit running...\n");
 141        time = ktime_to_us(ktime_get());
 142
 143        if (subdev->func->preinit) {
 144                int ret = subdev->func->preinit(subdev);
 145                if (ret) {
 146                        nvkm_error(subdev, "preinit failed, %d\n", ret);
 147                        return ret;
 148                }
 149        }
 150
 151        time = ktime_to_us(ktime_get()) - time;
 152        nvkm_trace(subdev, "preinit completed in %lldus\n", time);
 153        return 0;
 154}
 155
 156int
 157nvkm_subdev_init(struct nvkm_subdev *subdev)
 158{
 159        s64 time;
 160        int ret;
 161
 162        nvkm_trace(subdev, "init running...\n");
 163        time = ktime_to_us(ktime_get());
 164
 165        if (subdev->func->oneinit && !subdev->oneinit) {
 166                s64 time;
 167                nvkm_trace(subdev, "one-time init running...\n");
 168                time = ktime_to_us(ktime_get());
 169                ret = subdev->func->oneinit(subdev);
 170                if (ret) {
 171                        nvkm_error(subdev, "one-time init failed, %d\n", ret);
 172                        return ret;
 173                }
 174
 175                subdev->oneinit = true;
 176                time = ktime_to_us(ktime_get()) - time;
 177                nvkm_trace(subdev, "one-time init completed in %lldus\n", time);
 178        }
 179
 180        if (subdev->func->init) {
 181                ret = subdev->func->init(subdev);
 182                if (ret) {
 183                        nvkm_error(subdev, "init failed, %d\n", ret);
 184                        return ret;
 185                }
 186        }
 187
 188        time = ktime_to_us(ktime_get()) - time;
 189        nvkm_trace(subdev, "init completed in %lldus\n", time);
 190        return 0;
 191}
 192
 193void
 194nvkm_subdev_del(struct nvkm_subdev **psubdev)
 195{
 196        struct nvkm_subdev *subdev = *psubdev;
 197        s64 time;
 198
 199        if (subdev && !WARN_ON(!subdev->func)) {
 200                nvkm_trace(subdev, "destroy running...\n");
 201                time = ktime_to_us(ktime_get());
 202                if (subdev->func->dtor)
 203                        *psubdev = subdev->func->dtor(subdev);
 204                time = ktime_to_us(ktime_get()) - time;
 205                nvkm_trace(subdev, "destroy completed in %lldus\n", time);
 206                kfree(*psubdev);
 207                *psubdev = NULL;
 208        }
 209}
 210
 211void
 212nvkm_subdev_ctor(const struct nvkm_subdev_func *func,
 213                 struct nvkm_device *device, int index,
 214                 struct nvkm_subdev *subdev)
 215{
 216        const char *name = nvkm_subdev_name[index];
 217        subdev->func = func;
 218        subdev->device = device;
 219        subdev->index = index;
 220
 221        __mutex_init(&subdev->mutex, name, &nvkm_subdev_lock_class[index]);
 222        subdev->debug = nvkm_dbgopt(device->dbgopt, name);
 223}
 224