linux/drivers/gpu/drm/nouveau/core/subdev/instmem/base.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
  25#include "priv.h"
  26
  27/******************************************************************************
  28 * instmem object base implementation
  29 *****************************************************************************/
  30
  31void
  32_nouveau_instobj_dtor(struct nouveau_object *object)
  33{
  34        struct nouveau_instmem *imem = (void *)object->engine;
  35        struct nouveau_instobj *iobj = (void *)object;
  36
  37        mutex_lock(&nv_subdev(imem)->mutex);
  38        list_del(&iobj->head);
  39        mutex_unlock(&nv_subdev(imem)->mutex);
  40
  41        return nouveau_object_destroy(&iobj->base);
  42}
  43
  44int
  45nouveau_instobj_create_(struct nouveau_object *parent,
  46                        struct nouveau_object *engine,
  47                        struct nouveau_oclass *oclass,
  48                        int length, void **pobject)
  49{
  50        struct nouveau_instmem *imem = (void *)engine;
  51        struct nouveau_instobj *iobj;
  52        int ret;
  53
  54        ret = nouveau_object_create_(parent, engine, oclass, NV_MEMOBJ_CLASS,
  55                                     length, pobject);
  56        iobj = *pobject;
  57        if (ret)
  58                return ret;
  59
  60        mutex_lock(&imem->base.mutex);
  61        list_add(&iobj->head, &imem->list);
  62        mutex_unlock(&imem->base.mutex);
  63        return 0;
  64}
  65
  66/******************************************************************************
  67 * instmem subdev base implementation
  68 *****************************************************************************/
  69
  70static int
  71nouveau_instmem_alloc(struct nouveau_instmem *imem,
  72                      struct nouveau_object *parent, u32 size, u32 align,
  73                      struct nouveau_object **pobject)
  74{
  75        struct nouveau_object *engine = nv_object(imem);
  76        struct nouveau_instmem_impl *impl = (void *)engine->oclass;
  77        struct nouveau_instobj_args args = { .size = size, .align = align };
  78        return nouveau_object_ctor(parent, engine, impl->instobj, &args,
  79                                   sizeof(args), pobject);
  80}
  81
  82int
  83_nouveau_instmem_fini(struct nouveau_object *object, bool suspend)
  84{
  85        struct nouveau_instmem *imem = (void *)object;
  86        struct nouveau_instobj *iobj;
  87        int i, ret = 0;
  88
  89        if (suspend) {
  90                mutex_lock(&imem->base.mutex);
  91
  92                list_for_each_entry(iobj, &imem->list, head) {
  93                        iobj->suspend = vmalloc(iobj->size);
  94                        if (!iobj->suspend) {
  95                                ret = -ENOMEM;
  96                                break;
  97                        }
  98
  99                        for (i = 0; i < iobj->size; i += 4)
 100                                iobj->suspend[i / 4] = nv_ro32(iobj, i);
 101                }
 102
 103                mutex_unlock(&imem->base.mutex);
 104
 105                if (ret)
 106                        return ret;
 107        }
 108
 109        return nouveau_subdev_fini(&imem->base, suspend);
 110}
 111
 112int
 113_nouveau_instmem_init(struct nouveau_object *object)
 114{
 115        struct nouveau_instmem *imem = (void *)object;
 116        struct nouveau_instobj *iobj;
 117        int ret, i;
 118
 119        ret = nouveau_subdev_init(&imem->base);
 120        if (ret)
 121                return ret;
 122
 123        mutex_lock(&imem->base.mutex);
 124
 125        list_for_each_entry(iobj, &imem->list, head) {
 126                if (iobj->suspend) {
 127                        for (i = 0; i < iobj->size; i += 4)
 128                                nv_wo32(iobj, i, iobj->suspend[i / 4]);
 129                        vfree(iobj->suspend);
 130                        iobj->suspend = NULL;
 131                }
 132        }
 133
 134        mutex_unlock(&imem->base.mutex);
 135
 136        return 0;
 137}
 138
 139int
 140nouveau_instmem_create_(struct nouveau_object *parent,
 141                        struct nouveau_object *engine,
 142                        struct nouveau_oclass *oclass,
 143                        int length, void **pobject)
 144{
 145        struct nouveau_instmem *imem;
 146        int ret;
 147
 148        ret = nouveau_subdev_create_(parent, engine, oclass, 0,
 149                                     "INSTMEM", "instmem", length, pobject);
 150        imem = *pobject;
 151        if (ret)
 152                return ret;
 153
 154        INIT_LIST_HEAD(&imem->list);
 155        imem->alloc = nouveau_instmem_alloc;
 156        return 0;
 157}
 158