aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Miller <davem@davemloft.net>2009-02-14 04:51:07 -0500
committerDave Airlie <airlied@redhat.com>2009-03-13 00:24:02 -0400
commit6abf6bb0ff90bb77f9429bd0d90fc841c358daf3 (patch)
treebb291ce9a51dc8f8df33db5774d089ee8907ad33
parente8a894372b4ea05dc266ba7d7a7634315b6230e8 (diff)
drm: radeon: Use surface for PCI GART table.
This allocates a physical surface for the PCI GART table, this way no matter what other surface configurations exist the GART table will always be seen by the hardware properly. We encode the file pointer of the virtual surface allocate using a special cookie value, called PCIGART_FILE_PRIV. On the last close, we release that surface. Just to be doubly safe, we run the pcigart table setup with the main surface control register clear. Based upon ideas from David Airlie and Ben Benjamin Herrenschmidt. Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Dave Airlie <airlied@linux.ie>
-rw-r--r--drivers/gpu/drm/radeon/radeon_cp.c58
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_state.c1
3 files changed, 59 insertions, 1 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index 4a56e7d626a6..a18b3688a7f0 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -919,6 +919,46 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
919 } 919 }
920} 920}
921 921
922static int radeon_setup_pcigart_surface(drm_radeon_private_t *dev_priv)
923{
924 struct drm_ati_pcigart_info *gart_info = &dev_priv->gart_info;
925 struct radeon_virt_surface *vp;
926 int i;
927
928 for (i = 0; i < RADEON_MAX_SURFACES * 2; i++) {
929 if (!dev_priv->virt_surfaces[i].file_priv ||
930 dev_priv->virt_surfaces[i].file_priv == PCIGART_FILE_PRIV)
931 break;
932 }
933 if (i >= 2 * RADEON_MAX_SURFACES)
934 return -ENOMEM;
935 vp = &dev_priv->virt_surfaces[i];
936
937 for (i = 0; i < RADEON_MAX_SURFACES; i++) {
938 struct radeon_surface *sp = &dev_priv->surfaces[i];
939 if (sp->refcount)
940 continue;
941
942 vp->surface_index = i;
943 vp->lower = gart_info->bus_addr;
944 vp->upper = vp->lower + gart_info->table_size;
945 vp->flags = 0;
946 vp->file_priv = PCIGART_FILE_PRIV;
947
948 sp->refcount = 1;
949 sp->lower = vp->lower;
950 sp->upper = vp->upper;
951 sp->flags = 0;
952
953 RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, sp->flags);
954 RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * i, sp->lower);
955 RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * i, sp->upper);
956 return 0;
957 }
958
959 return -ENOMEM;
960}
961
922static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, 962static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
923 struct drm_file *file_priv) 963 struct drm_file *file_priv)
924{ 964{
@@ -1212,6 +1252,9 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
1212 } else 1252 } else
1213#endif 1253#endif
1214 { 1254 {
1255 u32 sctrl;
1256 int ret;
1257
1215 dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); 1258 dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
1216 /* if we have an offset set from userspace */ 1259 /* if we have an offset set from userspace */
1217 if (dev_priv->pcigart_offset_set) { 1260 if (dev_priv->pcigart_offset_set) {
@@ -1253,12 +1296,25 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
1253 } 1296 }
1254 } 1297 }
1255 1298
1256 if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { 1299 sctrl = RADEON_READ(RADEON_SURFACE_CNTL);
1300 RADEON_WRITE(RADEON_SURFACE_CNTL, 0);
1301 ret = drm_ati_pcigart_init(dev, &dev_priv->gart_info);
1302 RADEON_WRITE(RADEON_SURFACE_CNTL, sctrl);
1303
1304 if (!ret) {
1257 DRM_ERROR("failed to init PCI GART!\n"); 1305 DRM_ERROR("failed to init PCI GART!\n");
1258 radeon_do_cleanup_cp(dev); 1306 radeon_do_cleanup_cp(dev);
1259 return -ENOMEM; 1307 return -ENOMEM;
1260 } 1308 }
1261 1309
1310 ret = radeon_setup_pcigart_surface(dev_priv);
1311 if (ret) {
1312 DRM_ERROR("failed to setup GART surface!\n");
1313 drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info);
1314 radeon_do_cleanup_cp(dev);
1315 return ret;
1316 }
1317
1262 /* Turn on PCI GART */ 1318 /* Turn on PCI GART */
1263 radeon_set_pcigart(dev_priv, 1); 1319 radeon_set_pcigart(dev_priv, 1);
1264 } 1320 }
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
index 9b60a268dc7a..ecfd414bb99c 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.h
+++ b/drivers/gpu/drm/radeon/radeon_drv.h
@@ -217,6 +217,7 @@ struct radeon_virt_surface {
217 u32 upper; 217 u32 upper;
218 u32 flags; 218 u32 flags;
219 struct drm_file *file_priv; 219 struct drm_file *file_priv;
220#define PCIGART_FILE_PRIV ((void *) -1L)
220}; 221};
221 222
222#define RADEON_FLUSH_EMITED (1 << 0) 223#define RADEON_FLUSH_EMITED (1 << 0)
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c
index 03fea43dae75..043293ae6e48 100644
--- a/drivers/gpu/drm/radeon/radeon_state.c
+++ b/drivers/gpu/drm/radeon/radeon_state.c
@@ -3155,6 +3155,7 @@ void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
3155 3155
3156void radeon_driver_lastclose(struct drm_device *dev) 3156void radeon_driver_lastclose(struct drm_device *dev)
3157{ 3157{
3158 radeon_surfaces_release(PCIGART_FILE_PRIV, dev->dev_private);
3158 radeon_do_release(dev); 3159 radeon_do_release(dev);
3159} 3160}
3160 3161