aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-05-19 23:31:36 -0400
committerDave Airlie <airlied@redhat.com>2013-05-19 23:31:36 -0400
commitb7cb1c50c828adaee95e8ada0e55918686245992 (patch)
tree88694170f862f156e6f4a38b8fa207dba9200d45
parente9ced8e040ebe40e9953db90acbe7d0b58702ebb (diff)
parent81dff21b643f48c14010a97ffc799e1920d751e5 (diff)
Merge branch 'drm-nouveau-fixes-3.10' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next
Fixes some s/r problem with copy engines and ZCULL issues and playlist issues * 'drm-nouveau-fixes-3.10' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: drm/nouveau: ensure channels are stopped before saving fences for suspend drm/nv50/fifo: prevent races between clients updating playlists drm/nvc0/fifo: prevent CHAN_TABLE_ERROR:CHANNEL_PENDING on fifo fini drm/nvc0/fifo: prevent races between clients updating playlists drm/nve0/fifo: prevent races between clients updating playlists drm/nve0/ltcg: poke the partition count into yet another register drm/nvc0/ltcg: fix handling of disabled partitions drm/nvc0/ce: disable ce1 on a number of chipsets drm/nouveau/bios: fix thinko in ZM_MASK_ADD opcode drm/nouveau: fix build with nv50->nvc0
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nvc0.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/init.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c17
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c25
7 files changed, 47 insertions, 16 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
index 955af122c3a6..a36e64e98ef3 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
@@ -138,7 +138,6 @@ nvc0_identify(struct nouveau_device *device)
138 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass; 138 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
139 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 139 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
140 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 140 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
141 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
142 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 141 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass;
143 break; 142 break;
144 case 0xce: 143 case 0xce:
@@ -225,7 +224,6 @@ nvc0_identify(struct nouveau_device *device)
225 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass; 224 device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
226 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 225 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
227 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 226 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
228 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
229 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 227 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass;
230 break; 228 break;
231 case 0xc8: 229 case 0xc8:
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
index ddaeb5572903..89bf459d584b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
@@ -47,6 +47,7 @@ nv50_fifo_playlist_update(struct nv50_fifo_priv *priv)
47 struct nouveau_gpuobj *cur; 47 struct nouveau_gpuobj *cur;
48 int i, p; 48 int i, p;
49 49
50 mutex_lock(&nv_subdev(priv)->mutex);
50 cur = priv->playlist[priv->cur_playlist]; 51 cur = priv->playlist[priv->cur_playlist];
51 priv->cur_playlist = !priv->cur_playlist; 52 priv->cur_playlist = !priv->cur_playlist;
52 53
@@ -60,6 +61,7 @@ nv50_fifo_playlist_update(struct nv50_fifo_priv *priv)
60 nv_wr32(priv, 0x0032f4, cur->addr >> 12); 61 nv_wr32(priv, 0x0032f4, cur->addr >> 12);
61 nv_wr32(priv, 0x0032ec, p); 62 nv_wr32(priv, 0x0032ec, p);
62 nv_wr32(priv, 0x002500, 0x00000101); 63 nv_wr32(priv, 0x002500, 0x00000101);
64 mutex_unlock(&nv_subdev(priv)->mutex);
63} 65}
64 66
65static int 67static int
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
index 4d4a6b905370..46dfa68c47bb 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
@@ -71,6 +71,7 @@ nvc0_fifo_playlist_update(struct nvc0_fifo_priv *priv)
71 struct nouveau_gpuobj *cur; 71 struct nouveau_gpuobj *cur;
72 int i, p; 72 int i, p;
73 73
74 mutex_lock(&nv_subdev(priv)->mutex);
74 cur = priv->playlist[priv->cur_playlist]; 75 cur = priv->playlist[priv->cur_playlist];
75 priv->cur_playlist = !priv->cur_playlist; 76 priv->cur_playlist = !priv->cur_playlist;
76 77
@@ -87,6 +88,7 @@ nvc0_fifo_playlist_update(struct nvc0_fifo_priv *priv)
87 nv_wr32(priv, 0x002274, 0x01f00000 | (p >> 3)); 88 nv_wr32(priv, 0x002274, 0x01f00000 | (p >> 3));
88 if (!nv_wait(priv, 0x00227c, 0x00100000, 0x00000000)) 89 if (!nv_wait(priv, 0x00227c, 0x00100000, 0x00000000))
89 nv_error(priv, "playlist update failed\n"); 90 nv_error(priv, "playlist update failed\n");
91 mutex_unlock(&nv_subdev(priv)->mutex);
90} 92}
91 93
92static int 94static int
@@ -248,9 +250,17 @@ nvc0_fifo_chan_fini(struct nouveau_object *object, bool suspend)
248 struct nvc0_fifo_priv *priv = (void *)object->engine; 250 struct nvc0_fifo_priv *priv = (void *)object->engine;
249 struct nvc0_fifo_chan *chan = (void *)object; 251 struct nvc0_fifo_chan *chan = (void *)object;
250 u32 chid = chan->base.chid; 252 u32 chid = chan->base.chid;
253 u32 mask, engine;
251 254
252 nv_mask(priv, 0x003004 + (chid * 8), 0x00000001, 0x00000000); 255 nv_mask(priv, 0x003004 + (chid * 8), 0x00000001, 0x00000000);
253 nvc0_fifo_playlist_update(priv); 256 nvc0_fifo_playlist_update(priv);
257 mask = nv_rd32(priv, 0x0025a4);
258 for (engine = 0; mask && engine < 16; engine++) {
259 if (!(mask & (1 << engine)))
260 continue;
261 nv_mask(priv, 0x0025a8 + (engine * 4), 0x00000000, 0x00000000);
262 mask &= ~(1 << engine);
263 }
254 nv_wr32(priv, 0x003000 + (chid * 8), 0x00000000); 264 nv_wr32(priv, 0x003000 + (chid * 8), 0x00000000);
255 265
256 return nouveau_fifo_channel_fini(&chan->base, suspend); 266 return nouveau_fifo_channel_fini(&chan->base, suspend);
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
index 9151919fb831..56192a7242ae 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
@@ -94,11 +94,13 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
94 u32 match = (engine << 16) | 0x00000001; 94 u32 match = (engine << 16) | 0x00000001;
95 int i, p; 95 int i, p;
96 96
97 mutex_lock(&nv_subdev(priv)->mutex);
97 cur = engn->playlist[engn->cur_playlist]; 98 cur = engn->playlist[engn->cur_playlist];
98 if (unlikely(cur == NULL)) { 99 if (unlikely(cur == NULL)) {
99 int ret = nouveau_gpuobj_new(nv_object(priv), NULL, 100 int ret = nouveau_gpuobj_new(nv_object(priv), NULL,
100 0x8000, 0x1000, 0, &cur); 101 0x8000, 0x1000, 0, &cur);
101 if (ret) { 102 if (ret) {
103 mutex_unlock(&nv_subdev(priv)->mutex);
102 nv_error(priv, "playlist alloc failed\n"); 104 nv_error(priv, "playlist alloc failed\n");
103 return; 105 return;
104 } 106 }
@@ -122,6 +124,7 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
122 nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3)); 124 nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3));
123 if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000)) 125 if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000))
124 nv_error(priv, "playlist %d update timeout\n", engine); 126 nv_error(priv, "playlist %d update timeout\n", engine);
127 mutex_unlock(&nv_subdev(priv)->mutex);
125} 128}
126 129
127static int 130static int
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
index c300b5e7b670..c434d398d16f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
@@ -1940,8 +1940,8 @@ init_zm_mask_add(struct nvbios_init *init)
1940 trace("ZM_MASK_ADD\tR[0x%06x] &= 0x%08x += 0x%08x\n", addr, mask, add); 1940 trace("ZM_MASK_ADD\tR[0x%06x] &= 0x%08x += 0x%08x\n", addr, mask, add);
1941 init->offset += 13; 1941 init->offset += 13;
1942 1942
1943 data = init_rd32(init, addr) & mask; 1943 data = init_rd32(init, addr);
1944 data |= ((data + add) & ~mask); 1944 data = (data & mask) | ((data + add) & ~mask);
1945 init_wr32(init, addr, data); 1945 init_wr32(init, addr, data);
1946} 1946}
1947 1947
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
index e4940fb166e8..fb794e997fbc 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
@@ -29,7 +29,6 @@
29struct nvc0_ltcg_priv { 29struct nvc0_ltcg_priv {
30 struct nouveau_ltcg base; 30 struct nouveau_ltcg base;
31 u32 part_nr; 31 u32 part_nr;
32 u32 part_mask;
33 u32 subp_nr; 32 u32 subp_nr;
34 struct nouveau_mm tags; 33 struct nouveau_mm tags;
35 u32 num_tags; 34 u32 num_tags;
@@ -105,8 +104,6 @@ nvc0_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
105 104
106 /* wait until it's finished with clearing */ 105 /* wait until it's finished with clearing */
107 for (p = 0; p < priv->part_nr; ++p) { 106 for (p = 0; p < priv->part_nr; ++p) {
108 if (!(priv->part_mask & (1 << p)))
109 continue;
110 for (i = 0; i < priv->subp_nr; ++i) 107 for (i = 0; i < priv->subp_nr; ++i)
111 nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0); 108 nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0);
112 } 109 }
@@ -121,6 +118,8 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
121 int ret; 118 int ret;
122 119
123 nv_wr32(priv, 0x17e8d8, priv->part_nr); 120 nv_wr32(priv, 0x17e8d8, priv->part_nr);
121 if (nv_device(pfb)->card_type >= NV_E0)
122 nv_wr32(priv, 0x17e000, priv->part_nr);
124 123
125 /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */ 124 /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
126 priv->num_tags = (pfb->ram.size >> 17) / 4; 125 priv->num_tags = (pfb->ram.size >> 17) / 4;
@@ -167,16 +166,20 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
167{ 166{
168 struct nvc0_ltcg_priv *priv; 167 struct nvc0_ltcg_priv *priv;
169 struct nouveau_fb *pfb = nouveau_fb(parent); 168 struct nouveau_fb *pfb = nouveau_fb(parent);
170 int ret; 169 u32 parts, mask;
170 int ret, i;
171 171
172 ret = nouveau_ltcg_create(parent, engine, oclass, &priv); 172 ret = nouveau_ltcg_create(parent, engine, oclass, &priv);
173 *pobject = nv_object(priv); 173 *pobject = nv_object(priv);
174 if (ret) 174 if (ret)
175 return ret; 175 return ret;
176 176
177 priv->part_nr = nv_rd32(priv, 0x022438); 177 parts = nv_rd32(priv, 0x022438);
178 priv->part_mask = nv_rd32(priv, 0x022554); 178 mask = nv_rd32(priv, 0x022554);
179 179 for (i = 0; i < parts; i++) {
180 if (!(mask & (1 << i)))
181 priv->part_nr++;
182 }
180 priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28; 183 priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28;
181 184
182 nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ 185 nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 46c152ff0a80..383f4e6ea9d1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -453,18 +453,32 @@ nouveau_do_suspend(struct drm_device *dev)
453 NV_INFO(drm, "evicting buffers...\n"); 453 NV_INFO(drm, "evicting buffers...\n");
454 ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM); 454 ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
455 455
456 NV_INFO(drm, "waiting for kernel channels to go idle...\n");
457 if (drm->cechan) {
458 ret = nouveau_channel_idle(drm->cechan);
459 if (ret)
460 return ret;
461 }
462
463 if (drm->channel) {
464 ret = nouveau_channel_idle(drm->channel);
465 if (ret)
466 return ret;
467 }
468
469 NV_INFO(drm, "suspending client object trees...\n");
456 if (drm->fence && nouveau_fence(drm)->suspend) { 470 if (drm->fence && nouveau_fence(drm)->suspend) {
457 if (!nouveau_fence(drm)->suspend(drm)) 471 if (!nouveau_fence(drm)->suspend(drm))
458 return -ENOMEM; 472 return -ENOMEM;
459 } 473 }
460 474
461 NV_INFO(drm, "suspending client object trees...\n");
462 list_for_each_entry(cli, &drm->clients, head) { 475 list_for_each_entry(cli, &drm->clients, head) {
463 ret = nouveau_client_fini(&cli->base, true); 476 ret = nouveau_client_fini(&cli->base, true);
464 if (ret) 477 if (ret)
465 goto fail_client; 478 goto fail_client;
466 } 479 }
467 480
481 NV_INFO(drm, "suspending kernel object tree...\n");
468 ret = nouveau_client_fini(&drm->client.base, true); 482 ret = nouveau_client_fini(&drm->client.base, true);
469 if (ret) 483 if (ret)
470 goto fail_client; 484 goto fail_client;
@@ -514,17 +528,18 @@ nouveau_do_resume(struct drm_device *dev)
514 528
515 nouveau_agp_reset(drm); 529 nouveau_agp_reset(drm);
516 530
517 NV_INFO(drm, "resuming client object trees...\n"); 531 NV_INFO(drm, "resuming kernel object tree...\n");
518 nouveau_client_init(&drm->client.base); 532 nouveau_client_init(&drm->client.base);
519 nouveau_agp_init(drm); 533 nouveau_agp_init(drm);
520 534
535 NV_INFO(drm, "resuming client object trees...\n");
536 if (drm->fence && nouveau_fence(drm)->resume)
537 nouveau_fence(drm)->resume(drm);
538
521 list_for_each_entry(cli, &drm->clients, head) { 539 list_for_each_entry(cli, &drm->clients, head) {
522 nouveau_client_init(&cli->base); 540 nouveau_client_init(&cli->base);
523 } 541 }
524 542
525 if (drm->fence && nouveau_fence(drm)->resume)
526 nouveau_fence(drm)->resume(drm);
527
528 nouveau_run_vbios_init(dev); 543 nouveau_run_vbios_init(dev);
529 nouveau_pm_resume(dev); 544 nouveau_pm_resume(dev);
530 545