提交 6abf6bb0 编写于 作者: D David Miller 提交者: Dave Airlie

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: NDavid S. Miller <davem@davemloft.net>
Signed-off-by: NDave Airlie <airlied@linux.ie>
上级 e8a89437
...@@ -919,6 +919,46 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) ...@@ -919,6 +919,46 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
} }
} }
static int radeon_setup_pcigart_surface(drm_radeon_private_t *dev_priv)
{
struct drm_ati_pcigart_info *gart_info = &dev_priv->gart_info;
struct radeon_virt_surface *vp;
int i;
for (i = 0; i < RADEON_MAX_SURFACES * 2; i++) {
if (!dev_priv->virt_surfaces[i].file_priv ||
dev_priv->virt_surfaces[i].file_priv == PCIGART_FILE_PRIV)
break;
}
if (i >= 2 * RADEON_MAX_SURFACES)
return -ENOMEM;
vp = &dev_priv->virt_surfaces[i];
for (i = 0; i < RADEON_MAX_SURFACES; i++) {
struct radeon_surface *sp = &dev_priv->surfaces[i];
if (sp->refcount)
continue;
vp->surface_index = i;
vp->lower = gart_info->bus_addr;
vp->upper = vp->lower + gart_info->table_size;
vp->flags = 0;
vp->file_priv = PCIGART_FILE_PRIV;
sp->refcount = 1;
sp->lower = vp->lower;
sp->upper = vp->upper;
sp->flags = 0;
RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, sp->flags);
RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * i, sp->lower);
RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * i, sp->upper);
return 0;
}
return -ENOMEM;
}
static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
...@@ -1212,6 +1252,9 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, ...@@ -1212,6 +1252,9 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
} else } else
#endif #endif
{ {
u32 sctrl;
int ret;
dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
/* if we have an offset set from userspace */ /* if we have an offset set from userspace */
if (dev_priv->pcigart_offset_set) { 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,12 +1296,25 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
} }
} }
if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { sctrl = RADEON_READ(RADEON_SURFACE_CNTL);
RADEON_WRITE(RADEON_SURFACE_CNTL, 0);
ret = drm_ati_pcigart_init(dev, &dev_priv->gart_info);
RADEON_WRITE(RADEON_SURFACE_CNTL, sctrl);
if (!ret) {
DRM_ERROR("failed to init PCI GART!\n"); DRM_ERROR("failed to init PCI GART!\n");
radeon_do_cleanup_cp(dev); radeon_do_cleanup_cp(dev);
return -ENOMEM; return -ENOMEM;
} }
ret = radeon_setup_pcigart_surface(dev_priv);
if (ret) {
DRM_ERROR("failed to setup GART surface!\n");
drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info);
radeon_do_cleanup_cp(dev);
return ret;
}
/* Turn on PCI GART */ /* Turn on PCI GART */
radeon_set_pcigart(dev_priv, 1); radeon_set_pcigart(dev_priv, 1);
} }
......
...@@ -217,6 +217,7 @@ struct radeon_virt_surface { ...@@ -217,6 +217,7 @@ struct radeon_virt_surface {
u32 upper; u32 upper;
u32 flags; u32 flags;
struct drm_file *file_priv; struct drm_file *file_priv;
#define PCIGART_FILE_PRIV ((void *) -1L)
}; };
#define RADEON_FLUSH_EMITED (1 << 0) #define RADEON_FLUSH_EMITED (1 << 0)
......
...@@ -3155,6 +3155,7 @@ void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) ...@@ -3155,6 +3155,7 @@ void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
void radeon_driver_lastclose(struct drm_device *dev) void radeon_driver_lastclose(struct drm_device *dev)
{ {
radeon_surfaces_release(PCIGART_FILE_PRIV, dev->dev_private);
radeon_do_release(dev); radeon_do_release(dev);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册