[BACK]Return to nouveau_nvkm_subdev_instmem_base.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / external / bsd / drm2 / dist / drm / nouveau / nvkm / subdev / instmem

Annotation of src/sys/external/bsd/drm2/dist/drm/nouveau/nvkm/subdev/instmem/nouveau_nvkm_subdev_instmem_base.c, Revision 1.7

1.7     ! riastrad    1: /*     $NetBSD: nouveau_nvkm_subdev_instmem_base.c,v 1.6 2021/12/18 23:45:40 riastradh Exp $   */
1.1       riastrad    2:
                      3: /*
                      4:  * Copyright 2012 Red Hat Inc.
                      5:  *
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a
                      7:  * copy of this software and associated documentation files (the "Software"),
                      8:  * to deal in the Software without restriction, including without limitation
                      9:  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
                     10:  * and/or sell copies of the Software, and to permit persons to whom the
                     11:  * Software is furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
                     19:  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
                     20:  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
                     21:  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
                     22:  * OTHER DEALINGS IN THE SOFTWARE.
                     23:  *
                     24:  * Authors: Ben Skeggs
                     25:  */
                     26: #include <sys/cdefs.h>
1.7     ! riastrad   27: __KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_subdev_instmem_base.c,v 1.6 2021/12/18 23:45:40 riastradh Exp $");
1.1       riastrad   28:
                     29: #include "priv.h"
                     30:
                     31: #include <subdev/bar.h>
                     32:
1.3       riastrad   33: #ifdef __NetBSD__
                     34: #  define      __iomem __nvkm_memory_iomem
                     35: #endif
                     36:
1.2       riastrad   37: #ifdef __NetBSD__
                     38:
                     39: /*
                     40:  * XXX I think this should be done with bus_space, but the depth of
                     41:  * abstractions is dizzying and I'm not actually sure where these
                     42:  * pointers come from.
                     43:  */
                     44:
                     45: #  define      ioread32_native         fake_ioread32_native
                     46: #  define      iowrite32_native        fake_iowrite32_native
                     47:
                     48: static inline uint32_t
1.4       riastrad   49: ioread32_native(const void __iomem *ptr)
1.2       riastrad   50: {
                     51:        uint32_t v;
                     52:
                     53:        v = *(const uint32_t __iomem *)ptr;
                     54:        membar_consumer();
                     55:
                     56:        return v;
                     57: }
                     58:
                     59: static inline void
1.4       riastrad   60: iowrite32_native(uint32_t v, void __iomem *ptr)
1.2       riastrad   61: {
                     62:
                     63:        membar_producer();
                     64:        *(uint32_t __iomem *)ptr = v;
                     65: }
                     66:
                     67: #endif
1.6       riastrad   68: /******************************************************************************
                     69:  * instmem object base implementation
                     70:  *****************************************************************************/
                     71: static void
                     72: nvkm_instobj_load(struct nvkm_instobj *iobj)
                     73: {
                     74:        struct nvkm_memory *memory = &iobj->memory;
                     75:        const u64 size = nvkm_memory_size(memory);
                     76:        void __iomem *map;
                     77:        int i;
1.2       riastrad   78:
1.6       riastrad   79:        if (!(map = nvkm_kmap(memory))) {
                     80:                for (i = 0; i < size; i += 4)
                     81:                        nvkm_wo32(memory, i, iobj->suspend[i / 4]);
                     82:        } else {
                     83:                memcpy_toio(map, iobj->suspend, size);
                     84:        }
                     85:        nvkm_done(memory);
1.1       riastrad   86:
1.6       riastrad   87:        kvfree(iobj->suspend);
                     88:        iobj->suspend = NULL;
1.1       riastrad   89: }
                     90:
1.2       riastrad   91: #ifdef __NetBSD__
                     92: #  undef       ioread32_native
                     93: #  undef       iowrite32_native
                     94: #endif
                     95:
1.1       riastrad   96:
1.6       riastrad   97: static int
                     98: nvkm_instobj_save(struct nvkm_instobj *iobj)
1.1       riastrad   99: {
1.6       riastrad  100:        struct nvkm_memory *memory = &iobj->memory;
                    101:        const u64 size = nvkm_memory_size(memory);
                    102:        void __iomem *map;
                    103:        int i;
1.1       riastrad  104:
1.6       riastrad  105:        iobj->suspend = kvmalloc(size, GFP_KERNEL);
                    106:        if (!iobj->suspend)
                    107:                return -ENOMEM;
                    108:
                    109:        if (!(map = nvkm_kmap(memory))) {
                    110:                for (i = 0; i < size; i += 4)
                    111:                        iobj->suspend[i / 4] = nvkm_ro32(memory, i);
                    112:        } else {
                    113:                memcpy_fromio(iobj->suspend, map, size);
                    114:        }
                    115:        nvkm_done(memory);
                    116:        return 0;
1.1       riastrad  117: }
                    118:
1.6       riastrad  119: void
                    120: nvkm_instobj_dtor(struct nvkm_instmem *imem, struct nvkm_instobj *iobj)
1.1       riastrad  121: {
1.6       riastrad  122:        spin_lock(&imem->lock);
                    123:        list_del(&iobj->head);
                    124:        spin_unlock(&imem->lock);
1.1       riastrad  125: }
                    126:
1.6       riastrad  127: void
                    128: nvkm_instobj_ctor(const struct nvkm_memory_func *func,
                    129:                  struct nvkm_instmem *imem, struct nvkm_instobj *iobj)
1.1       riastrad  130: {
1.6       riastrad  131:        nvkm_memory_ctor(func, &iobj->memory);
                    132:        iobj->suspend = NULL;
                    133:        spin_lock(&imem->lock);
                    134:        list_add_tail(&iobj->head, &imem->list);
                    135:        spin_unlock(&imem->lock);
1.1       riastrad  136: }
                    137:
                    138: int
                    139: nvkm_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero,
                    140:                 struct nvkm_memory **pmemory)
                    141: {
1.6       riastrad  142:        struct nvkm_subdev *subdev = &imem->subdev;
1.1       riastrad  143:        struct nvkm_memory *memory = NULL;
                    144:        u32 offset;
                    145:        int ret;
                    146:
                    147:        ret = imem->func->memory_new(imem, size, align, zero, &memory);
1.6       riastrad  148:        if (ret) {
                    149:                nvkm_error(subdev, "OOM: %08x %08x %d\n", size, align, ret);
1.1       riastrad  150:                goto done;
1.6       riastrad  151:        }
1.1       riastrad  152:
1.7     ! riastrad  153:        nvkm_trace(subdev, "new %08x %08x %d: %010"PRIx64" %010"PRIx64"\n", size, align,
1.6       riastrad  154:                   zero, nvkm_memory_addr(memory), nvkm_memory_size(memory));
1.1       riastrad  155:
                    156:        if (!imem->func->zero && zero) {
                    157:                void __iomem *map = nvkm_kmap(memory);
                    158:                if (unlikely(!map)) {
                    159:                        for (offset = 0; offset < size; offset += 4)
                    160:                                nvkm_wo32(memory, offset, 0x00000000);
                    161:                } else {
                    162:                        memset_io(map, 0x00, size);
                    163:                }
                    164:                nvkm_done(memory);
                    165:        }
                    166:
                    167: done:
                    168:        if (ret)
1.6       riastrad  169:                nvkm_memory_unref(&memory);
1.1       riastrad  170:        *pmemory = memory;
                    171:        return ret;
                    172: }
                    173:
                    174: /******************************************************************************
                    175:  * instmem subdev base implementation
                    176:  *****************************************************************************/
                    177:
                    178: u32
                    179: nvkm_instmem_rd32(struct nvkm_instmem *imem, u32 addr)
                    180: {
                    181:        return imem->func->rd32(imem, addr);
                    182: }
                    183:
                    184: void
                    185: nvkm_instmem_wr32(struct nvkm_instmem *imem, u32 addr, u32 data)
                    186: {
                    187:        return imem->func->wr32(imem, addr, data);
                    188: }
                    189:
1.6       riastrad  190: void
                    191: nvkm_instmem_boot(struct nvkm_instmem *imem)
                    192: {
                    193:        /* Separate bootstrapped objects from normal list, as we need
                    194:         * to make sure they're accessed with the slowpath on suspend
                    195:         * and resume.
                    196:         */
                    197:        struct nvkm_instobj *iobj, *itmp;
                    198:        spin_lock(&imem->lock);
                    199:        list_for_each_entry_safe(iobj, itmp, &imem->list, head) {
                    200:                list_move_tail(&iobj->head, &imem->boot);
                    201:        }
                    202:        spin_unlock(&imem->lock);
                    203: }
                    204:
1.1       riastrad  205: static int
                    206: nvkm_instmem_fini(struct nvkm_subdev *subdev, bool suspend)
                    207: {
                    208:        struct nvkm_instmem *imem = nvkm_instmem(subdev);
                    209:        struct nvkm_instobj *iobj;
                    210:
                    211:        if (suspend) {
                    212:                list_for_each_entry(iobj, &imem->list, head) {
1.6       riastrad  213:                        int ret = nvkm_instobj_save(iobj);
                    214:                        if (ret)
                    215:                                return ret;
                    216:                }
1.1       riastrad  217:
1.6       riastrad  218:                nvkm_bar_bar2_fini(subdev->device);
1.1       riastrad  219:
1.6       riastrad  220:                list_for_each_entry(iobj, &imem->boot, head) {
                    221:                        int ret = nvkm_instobj_save(iobj);
                    222:                        if (ret)
                    223:                                return ret;
1.1       riastrad  224:                }
                    225:        }
                    226:
1.6       riastrad  227:        if (imem->func->fini)
                    228:                imem->func->fini(imem);
1.1       riastrad  229:
                    230:        return 0;
                    231: }
                    232:
                    233: static int
                    234: nvkm_instmem_init(struct nvkm_subdev *subdev)
                    235: {
                    236:        struct nvkm_instmem *imem = nvkm_instmem(subdev);
                    237:        struct nvkm_instobj *iobj;
1.6       riastrad  238:
                    239:        list_for_each_entry(iobj, &imem->boot, head) {
                    240:                if (iobj->suspend)
                    241:                        nvkm_instobj_load(iobj);
                    242:        }
                    243:
                    244:        nvkm_bar_bar2_init(subdev->device);
1.1       riastrad  245:
                    246:        list_for_each_entry(iobj, &imem->list, head) {
1.6       riastrad  247:                if (iobj->suspend)
                    248:                        nvkm_instobj_load(iobj);
1.1       riastrad  249:        }
                    250:
                    251:        return 0;
                    252: }
                    253:
1.6       riastrad  254: static int
                    255: nvkm_instmem_oneinit(struct nvkm_subdev *subdev)
                    256: {
                    257:        struct nvkm_instmem *imem = nvkm_instmem(subdev);
                    258:        if (imem->func->oneinit)
                    259:                return imem->func->oneinit(imem);
                    260:        return 0;
                    261: }
                    262:
1.1       riastrad  263: static void *
                    264: nvkm_instmem_dtor(struct nvkm_subdev *subdev)
                    265: {
                    266:        struct nvkm_instmem *imem = nvkm_instmem(subdev);
                    267:        if (imem->func->dtor)
                    268:                return imem->func->dtor(imem);
                    269:        return imem;
                    270: }
                    271:
                    272: static const struct nvkm_subdev_func
                    273: nvkm_instmem = {
                    274:        .dtor = nvkm_instmem_dtor,
                    275:        .oneinit = nvkm_instmem_oneinit,
                    276:        .init = nvkm_instmem_init,
                    277:        .fini = nvkm_instmem_fini,
                    278: };
                    279:
                    280: void
                    281: nvkm_instmem_ctor(const struct nvkm_instmem_func *func,
                    282:                  struct nvkm_device *device, int index,
                    283:                  struct nvkm_instmem *imem)
                    284: {
1.6       riastrad  285:        nvkm_subdev_ctor(&nvkm_instmem, device, index, &imem->subdev);
1.1       riastrad  286:        imem->func = func;
                    287:        spin_lock_init(&imem->lock);
                    288:        INIT_LIST_HEAD(&imem->list);
1.6       riastrad  289:        INIT_LIST_HEAD(&imem->boot);
1.1       riastrad  290: }

CVSweb <webmaster@jp.NetBSD.org>