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>