diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-11-26 20:05:36 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-11-28 18:58:12 -0500 |
commit | edc260d06181cbf38d5cd326e6cf824d8e2e0eaf (patch) | |
tree | 2d840c53ad09f1bdc02a29948bdd0d1f0349d329 | |
parent | c9aa763fe9690a334d0636f88e6eb85340f36f89 (diff) |
drm/nouveau/fifo: trigger engine context unload before zeroing context pointer
Fixes a PCE0 page fault noticed on NVD9 during module unload.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 7 |
4 files changed, 25 insertions, 25 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 3d3ed547ed4c..bd096364f680 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | |||
@@ -112,14 +112,6 @@ nv50_fifo_context_detach(struct nouveau_object *parent, bool suspend, | |||
112 | return -EINVAL; | 112 | return -EINVAL; |
113 | } | 113 | } |
114 | 114 | ||
115 | nv_wo32(base->eng, addr + 0x00, 0x00000000); | ||
116 | nv_wo32(base->eng, addr + 0x04, 0x00000000); | ||
117 | nv_wo32(base->eng, addr + 0x08, 0x00000000); | ||
118 | nv_wo32(base->eng, addr + 0x0c, 0x00000000); | ||
119 | nv_wo32(base->eng, addr + 0x10, 0x00000000); | ||
120 | nv_wo32(base->eng, addr + 0x14, 0x00000000); | ||
121 | bar->flush(bar); | ||
122 | |||
123 | /* HW bug workaround: | 115 | /* HW bug workaround: |
124 | * | 116 | * |
125 | * PFIFO will hang forever if the connected engines don't report | 117 | * PFIFO will hang forever if the connected engines don't report |
@@ -141,8 +133,18 @@ nv50_fifo_context_detach(struct nouveau_object *parent, bool suspend, | |||
141 | if (suspend) | 133 | if (suspend) |
142 | ret = -EBUSY; | 134 | ret = -EBUSY; |
143 | } | 135 | } |
144 | |||
145 | nv_wr32(priv, 0x00b860, me); | 136 | nv_wr32(priv, 0x00b860, me); |
137 | |||
138 | if (ret == 0) { | ||
139 | nv_wo32(base->eng, addr + 0x00, 0x00000000); | ||
140 | nv_wo32(base->eng, addr + 0x04, 0x00000000); | ||
141 | nv_wo32(base->eng, addr + 0x08, 0x00000000); | ||
142 | nv_wo32(base->eng, addr + 0x0c, 0x00000000); | ||
143 | nv_wo32(base->eng, addr + 0x10, 0x00000000); | ||
144 | nv_wo32(base->eng, addr + 0x14, 0x00000000); | ||
145 | bar->flush(bar); | ||
146 | } | ||
147 | |||
146 | return ret; | 148 | return ret; |
147 | } | 149 | } |
148 | 150 | ||
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 7969df948cfa..1eb1c512f503 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | |||
@@ -95,14 +95,6 @@ nv84_fifo_context_detach(struct nouveau_object *parent, bool suspend, | |||
95 | return -EINVAL; | 95 | return -EINVAL; |
96 | } | 96 | } |
97 | 97 | ||
98 | nv_wo32(base->eng, addr + 0x00, 0x00000000); | ||
99 | nv_wo32(base->eng, addr + 0x04, 0x00000000); | ||
100 | nv_wo32(base->eng, addr + 0x08, 0x00000000); | ||
101 | nv_wo32(base->eng, addr + 0x0c, 0x00000000); | ||
102 | nv_wo32(base->eng, addr + 0x10, 0x00000000); | ||
103 | nv_wo32(base->eng, addr + 0x14, 0x00000000); | ||
104 | bar->flush(bar); | ||
105 | |||
106 | save = nv_mask(priv, 0x002520, 0x0000003f, 1 << engn); | 98 | save = nv_mask(priv, 0x002520, 0x0000003f, 1 << engn); |
107 | nv_wr32(priv, 0x0032fc, nv_gpuobj(base)->addr >> 12); | 99 | nv_wr32(priv, 0x0032fc, nv_gpuobj(base)->addr >> 12); |
108 | done = nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff); | 100 | done = nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff); |
@@ -112,6 +104,14 @@ nv84_fifo_context_detach(struct nouveau_object *parent, bool suspend, | |||
112 | if (suspend) | 104 | if (suspend) |
113 | return -EBUSY; | 105 | return -EBUSY; |
114 | } | 106 | } |
107 | |||
108 | nv_wo32(base->eng, addr + 0x00, 0x00000000); | ||
109 | nv_wo32(base->eng, addr + 0x04, 0x00000000); | ||
110 | nv_wo32(base->eng, addr + 0x08, 0x00000000); | ||
111 | nv_wo32(base->eng, addr + 0x0c, 0x00000000); | ||
112 | nv_wo32(base->eng, addr + 0x10, 0x00000000); | ||
113 | nv_wo32(base->eng, addr + 0x14, 0x00000000); | ||
114 | bar->flush(bar); | ||
115 | return 0; | 115 | return 0; |
116 | } | 116 | } |
117 | 117 | ||
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index 8f25255247e5..b4365dde1859 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | |||
@@ -147,10 +147,6 @@ nvc0_fifo_context_detach(struct nouveau_object *parent, bool suspend, | |||
147 | return -EINVAL; | 147 | return -EINVAL; |
148 | } | 148 | } |
149 | 149 | ||
150 | nv_wo32(base, addr + 0x00, 0x00000000); | ||
151 | nv_wo32(base, addr + 0x04, 0x00000000); | ||
152 | bar->flush(bar); | ||
153 | |||
154 | nv_wr32(priv, 0x002634, chan->base.chid); | 150 | nv_wr32(priv, 0x002634, chan->base.chid); |
155 | if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { | 151 | if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { |
156 | nv_error(priv, "channel %d kick timeout\n", chan->base.chid); | 152 | nv_error(priv, "channel %d kick timeout\n", chan->base.chid); |
@@ -158,6 +154,9 @@ nvc0_fifo_context_detach(struct nouveau_object *parent, bool suspend, | |||
158 | return -EBUSY; | 154 | return -EBUSY; |
159 | } | 155 | } |
160 | 156 | ||
157 | nv_wo32(base, addr + 0x00, 0x00000000); | ||
158 | nv_wo32(base, addr + 0x04, 0x00000000); | ||
159 | bar->flush(bar); | ||
161 | return 0; | 160 | return 0; |
162 | } | 161 | } |
163 | 162 | ||
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 9df59c028e45..c930da99c2c1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | |||
@@ -182,10 +182,6 @@ nve0_fifo_context_detach(struct nouveau_object *parent, bool suspend, | |||
182 | return -EINVAL; | 182 | return -EINVAL; |
183 | } | 183 | } |
184 | 184 | ||
185 | nv_wo32(base, addr + 0x00, 0x00000000); | ||
186 | nv_wo32(base, addr + 0x04, 0x00000000); | ||
187 | bar->flush(bar); | ||
188 | |||
189 | nv_wr32(priv, 0x002634, chan->base.chid); | 185 | nv_wr32(priv, 0x002634, chan->base.chid); |
190 | if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { | 186 | if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { |
191 | nv_error(priv, "channel %d kick timeout\n", chan->base.chid); | 187 | nv_error(priv, "channel %d kick timeout\n", chan->base.chid); |
@@ -193,6 +189,9 @@ nve0_fifo_context_detach(struct nouveau_object *parent, bool suspend, | |||
193 | return -EBUSY; | 189 | return -EBUSY; |
194 | } | 190 | } |
195 | 191 | ||
192 | nv_wo32(base, addr + 0x00, 0x00000000); | ||
193 | nv_wo32(base, addr + 0x04, 0x00000000); | ||
194 | bar->flush(bar); | ||
196 | return 0; | 195 | return 0; |
197 | } | 196 | } |
198 | 197 | ||