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