aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_object.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-09-01 01:24:33 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-09-24 02:20:28 -0400
commit5125bfd88608012d58652ac7ea6a03a78773200f (patch)
tree8ccb36c6a023392e3c8a9f2c4e84c74ccdcaeb44 /drivers/gpu/drm/nouveau/nouveau_object.c
parent43efc9ce25c6956133c07394a6fa44ef2c9268a4 (diff)
drm/nv50: allow gpuobjs that aren't mapped into aperture
Reviewed-by: Francisco Jerez <currojerez@riseup.net> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_object.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_object.c102
1 files changed, 77 insertions, 25 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c
index 4bcea11f54e6..df445fcb8321 100644
--- a/drivers/gpu/drm/nouveau/nouveau_object.c
+++ b/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -75,7 +75,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
75 struct drm_nouveau_private *dev_priv = dev->dev_private; 75 struct drm_nouveau_private *dev_priv = dev->dev_private;
76 struct nouveau_engine *engine = &dev_priv->engine; 76 struct nouveau_engine *engine = &dev_priv->engine;
77 struct nouveau_gpuobj *gpuobj; 77 struct nouveau_gpuobj *gpuobj;
78 struct drm_mm *pramin = NULL; 78 struct drm_mm_node *ramin = NULL;
79 int ret; 79 int ret;
80 80
81 NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n", 81 NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n",
@@ -95,36 +95,42 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
95 95
96 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); 96 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
97 97
98 /* Choose between global instmem heap, and per-channel private
99 * instmem heap. On <NV50 allow requests for private instmem
100 * to be satisfied from global heap if no per-channel area
101 * available.
102 */
103 if (chan) { 98 if (chan) {
104 NV_DEBUG(dev, "channel heap\n"); 99 NV_DEBUG(dev, "channel heap\n");
105 pramin = &chan->ramin_heap; 100
101 ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0);
102 if (ramin)
103 ramin = drm_mm_get_block(ramin, size, align);
104
105 if (!ramin) {
106 nouveau_gpuobj_ref(NULL, &gpuobj);
107 return -ENOMEM;
108 }
106 } else { 109 } else {
107 NV_DEBUG(dev, "global heap\n"); 110 NV_DEBUG(dev, "global heap\n");
108 pramin = &dev_priv->ramin_heap;
109 111
112 /* allocate backing pages, sets vinst */
110 ret = engine->instmem.populate(dev, gpuobj, &size); 113 ret = engine->instmem.populate(dev, gpuobj, &size);
111 if (ret) { 114 if (ret) {
112 nouveau_gpuobj_ref(NULL, &gpuobj); 115 nouveau_gpuobj_ref(NULL, &gpuobj);
113 return ret; 116 return ret;
114 } 117 }
115 }
116 118
117 /* Allocate a chunk of the PRAMIN aperture */ 119 /* try and get aperture space */
118 gpuobj->im_pramin = drm_mm_search_free(pramin, size, align, 0); 120 ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0);
119 if (gpuobj->im_pramin) 121 if (ramin)
120 gpuobj->im_pramin = drm_mm_get_block(gpuobj->im_pramin, size, align); 122 ramin = drm_mm_get_block(ramin, size, align);
121 123
122 if (!gpuobj->im_pramin) { 124 /* on nv50 it's ok to fail, we have a fallback path */
123 nouveau_gpuobj_ref(NULL, &gpuobj); 125 if (!ramin && dev_priv->card_type < NV_50) {
124 return -ENOMEM; 126 nouveau_gpuobj_ref(NULL, &gpuobj);
127 return -ENOMEM;
128 }
125 } 129 }
126 130
127 if (!chan) { 131 /* if we got a chunk of the aperture, map pages into it */
132 gpuobj->im_pramin = ramin;
133 if (!chan && gpuobj->im_pramin) {
128 ret = engine->instmem.bind(dev, gpuobj); 134 ret = engine->instmem.bind(dev, gpuobj);
129 if (ret) { 135 if (ret) {
130 nouveau_gpuobj_ref(NULL, &gpuobj); 136 nouveau_gpuobj_ref(NULL, &gpuobj);
@@ -134,7 +140,10 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
134 140
135 /* calculate the various different addresses for the object */ 141 /* calculate the various different addresses for the object */
136 if (chan) { 142 if (chan) {
137 gpuobj->pinst = gpuobj->im_pramin->start + chan->ramin->pinst; 143 gpuobj->pinst = chan->ramin->pinst;
144 if (gpuobj->pinst != ~0)
145 gpuobj->pinst += gpuobj->im_pramin->start;
146
138 if (dev_priv->card_type < NV_50) { 147 if (dev_priv->card_type < NV_50) {
139 gpuobj->cinst = gpuobj->pinst; 148 gpuobj->cinst = gpuobj->pinst;
140 } else { 149 } else {
@@ -143,7 +152,10 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
143 chan->ramin->vinst; 152 chan->ramin->vinst;
144 } 153 }
145 } else { 154 } else {
146 gpuobj->pinst = gpuobj->im_pramin->start; 155 if (gpuobj->im_pramin)
156 gpuobj->pinst = gpuobj->im_pramin->start;
157 else
158 gpuobj->pinst = ~0;
147 gpuobj->cinst = 0xdeadbeef; 159 gpuobj->cinst = 0xdeadbeef;
148 } 160 }
149 161
@@ -168,6 +180,8 @@ nouveau_gpuobj_early_init(struct drm_device *dev)
168 NV_DEBUG(dev, "\n"); 180 NV_DEBUG(dev, "\n");
169 181
170 INIT_LIST_HEAD(&dev_priv->gpuobj_list); 182 INIT_LIST_HEAD(&dev_priv->gpuobj_list);
183 spin_lock_init(&dev_priv->ramin_lock);
184 dev_priv->ramin_base = ~0;
171 185
172 return 0; 186 return 0;
173} 187}
@@ -650,12 +664,15 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
650 * locations determined during init. 664 * locations determined during init.
651 */ 665 */
652 if (dev_priv->card_type >= NV_50) { 666 if (dev_priv->card_type >= NV_50) {
653 uint32_t vm_offset, pde; 667 u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200;
668 u64 vm_vinst = chan->ramin->vinst + pgd_offs;
669 u32 vm_pinst = chan->ramin->pinst;
670 u32 pde;
654 671
655 vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200; 672 if (vm_pinst != ~0)
656 vm_offset += chan->ramin->im_pramin->start; 673 vm_pinst += pgd_offs;
657 674
658 ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000, 675 ret = nouveau_gpuobj_new_fake(dev, vm_pinst, vm_vinst, 0x4000,
659 0, &chan->vm_pd); 676 0, &chan->vm_pd);
660 if (ret) 677 if (ret)
661 return ret; 678 return ret;
@@ -941,11 +958,46 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
941u32 958u32
942nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset) 959nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset)
943{ 960{
944 return nv_ri32(gpuobj->dev, gpuobj->pinst + offset); 961 struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
962 struct drm_device *dev = gpuobj->dev;
963
964 if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) {
965 u64 ptr = gpuobj->vinst + offset;
966 u32 base = ptr >> 16;
967 u32 val;
968
969 spin_lock(&dev_priv->ramin_lock);
970 if (dev_priv->ramin_base != base) {
971 dev_priv->ramin_base = base;
972 nv_wr32(dev, 0x001700, dev_priv->ramin_base);
973 }
974 val = nv_rd32(dev, 0x700000 + (ptr & 0xffff));
975 spin_unlock(&dev_priv->ramin_lock);
976 return val;
977 }
978
979 return nv_ri32(dev, gpuobj->pinst + offset);
945} 980}
946 981
947void 982void
948nv_wo32(struct nouveau_gpuobj *gpuobj, u32 offset, u32 val) 983nv_wo32(struct nouveau_gpuobj *gpuobj, u32 offset, u32 val)
949{ 984{
950 nv_wi32(gpuobj->dev, gpuobj->pinst + offset, val); 985 struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
986 struct drm_device *dev = gpuobj->dev;
987
988 if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) {
989 u64 ptr = gpuobj->vinst + offset;
990 u32 base = ptr >> 16;
991
992 spin_lock(&dev_priv->ramin_lock);
993 if (dev_priv->ramin_base != base) {
994 dev_priv->ramin_base = base;
995 nv_wr32(dev, 0x001700, dev_priv->ramin_base);
996 }
997 nv_wr32(dev, 0x700000 + (ptr & 0xffff), val);
998 spin_unlock(&dev_priv->ramin_lock);
999 return;
1000 }
1001
1002 nv_wi32(dev, gpuobj->pinst + offset, val);
951} 1003}