summaryrefslogtreecommitdiff
path: root/shared-core
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@jbarnes-t61.(none)>2008-06-11 15:59:01 -0700
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-06-11 15:59:01 -0700
commit4a2e29bf9982165deeeabb5c585fc0a8a659f380 (patch)
treed9aeb96a387bac3a8209292d9cc12f3b7c0c93bd /shared-core
parentf5412a944fa4666e25f4fa27b6ed85c21ccb65a0 (diff)
Use GEM in modesetting
Use GEM for ring buffer setup and framebuffer allocation. This means reworking the hardware status page stuff a bit (just use the basic range allocator for vram for now) and #ifdef'ing out the TTM & DRI2 code. Works well enough to load/unload several times and display fbcon on my T61 (though there's still some unexplained console corruption).
Diffstat (limited to 'shared-core')
-rw-r--r--shared-core/i915_dma.c39
-rw-r--r--shared-core/i915_drv.h41
-rw-r--r--shared-core/i915_init.c193
3 files changed, 129 insertions, 144 deletions
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index 1e51e702..0cd920de 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -139,8 +139,8 @@ int i915_dma_cleanup(struct drm_device * dev)
I915_WRITE(0x02080, 0x1ffff000);
}
- if (dev_priv->status_gfx_addr) {
- dev_priv->status_gfx_addr = 0;
+ if (dev_priv->hws_agpoffset) {
+ dev_priv->hws_agpoffset = 0;
drm_core_ioremapfree(&dev_priv->hws_map, dev);
I915_WRITE(0x02080, 0x1ffff000);
}
@@ -148,7 +148,7 @@ int i915_dma_cleanup(struct drm_device * dev)
return 0;
}
-#if defined(I915_HAVE_BUFFER)
+#if defined(I915_HAVE_BUFFER) && defined(DRI2)
#define DRI2_SAREA_BLOCK_TYPE(b) ((b) >> 16)
#define DRI2_SAREA_BLOCK_SIZE(b) ((b) & 0xffff)
#define DRI2_SAREA_BLOCK_NEXT(p) \
@@ -276,10 +276,10 @@ static int i915_initialize(struct drm_device * dev,
DRM_ERROR("Can not allocate hardware status page\n");
return -ENOMEM;
}
- dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+ dev_priv->hws_vaddr = dev_priv->status_page_dmah->vaddr;
dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+ memset(dev_priv->hws_vaddr, 0, PAGE_SIZE);
I915_WRITE(0x02080, dev_priv->dma_status_page);
}
@@ -289,7 +289,7 @@ static int i915_initialize(struct drm_device * dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
mutex_init(&dev_priv->cmdbuf_mutex);
}
-
+#ifdef DRI2
if (init->func == I915_INIT_DMA2) {
int ret = setup_dri2_sarea(dev, file_priv, init);
if (ret) {
@@ -298,7 +298,8 @@ static int i915_initialize(struct drm_device * dev,
return ret;
}
}
-#endif
+#endif /* DRI2 */
+#endif /* I915_HAVE_BUFFER */
return 0;
}
@@ -319,16 +320,16 @@ static int i915_dma_resume(struct drm_device * dev)
}
/* Program Hardware Status Page */
- if (!dev_priv->hw_status_page) {
+ if (!dev_priv->hws_vaddr) {
DRM_ERROR("Can not find hardware status page\n");
return -EINVAL;
}
- DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+ DRM_DEBUG("hw status page @ %p\n", dev_priv->hws_vaddr);
- if (dev_priv->status_gfx_addr != 0)
- I915_WRITE(0x02080, dev_priv->status_gfx_addr);
+ if (dev_priv->hws_agpoffset != 0)
+ I915_WRITE(HWS_PGA, dev_priv->hws_agpoffset);
else
- I915_WRITE(0x02080, dev_priv->dma_status_page);
+ I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
DRM_DEBUG("Enabled hardware status page\n");
return 0;
@@ -1032,7 +1033,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr);
- dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
+ dev_priv->hws_agpoffset = hws->addr & (0x1ffff<<12);
dev_priv->hws_map.offset = dev->agp->base + hws->addr;
dev_priv->hws_map.size = 4*1024;
@@ -1043,18 +1044,18 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
drm_core_ioremap(&dev_priv->hws_map, dev);
if (dev_priv->hws_map.handle == NULL) {
i915_dma_cleanup(dev);
- dev_priv->status_gfx_addr = 0;
+ dev_priv->hws_agpoffset = 0;
DRM_ERROR("can not ioremap virtual address for"
" G33 hw status page\n");
return -ENOMEM;
}
- dev_priv->hw_status_page = dev_priv->hws_map.handle;
+ dev_priv->hws_vaddr = dev_priv->hws_map.handle;
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
- I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
+ memset(dev_priv->hws_vaddr, 0, PAGE_SIZE);
+ I915_WRITE(HWS_PGA, dev_priv->hws_agpoffset);
DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
- dev_priv->status_gfx_addr);
- DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
+ dev_priv->hws_agpoffset);
+ DRM_DEBUG("load hws at %p\n", dev_priv->hws_vaddr);
return 0;
}
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index cfb064ff..06aa00ab 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -115,8 +115,6 @@ struct drm_i915_master_private {
struct drm_i915_private {
struct drm_device *dev;
- struct drm_buffer_object *ring_buffer;
-
drm_local_map_t *mmio_map;
unsigned long mmiobase;
@@ -125,12 +123,12 @@ struct drm_i915_private {
struct drm_i915_ring_buffer ring;
struct drm_dma_handle *status_page_dmah;
- void *hw_status_page;
dma_addr_t dma_status_page;
uint32_t counter;
- unsigned int status_gfx_addr;
+ uint32_t hws_agpoffset;
drm_local_map_t hws_map;
- struct drm_buffer_object *hws_bo;
+ void *hws_vaddr;
+ struct drm_memrange_node *hws;
unsigned int cpp;
@@ -152,6 +150,8 @@ struct drm_i915_private {
bool cursor_needs_physical;
+ struct drm_memrange vram;
+
#ifdef I915_HAVE_FENCE
uint32_t flush_sequence;
uint32_t flush_flags;
@@ -176,17 +176,17 @@ struct drm_i915_private {
struct drm_display_mode *panel_fixed_mode;
struct drm_display_mode *vbt_mode; /* if any */
-#if defined(I915_HAVE_BUFFER)
+#if defined(I915_HAVE_BUFFER) && defined(DRI2)
/* DRI2 sarea */
- struct drm_buffer_object *sarea_bo;
- struct drm_bo_kmap_obj sarea_kmap;
+ struct drm_gem_object *sarea_object;
+ struct drm_bo_kmap_obj sarea_kmap;
+#endif
/* Feature bits from the VBIOS */
int int_tv_support:1;
int lvds_dither:1;
int lvds_vbt:1;
int int_crt_support:1;
-#endif
struct {
struct drm_memrange gtt_space;
@@ -483,7 +483,7 @@ extern void i915_invalidate_reported_sequence(struct drm_device *dev);
#endif
-#ifdef I915_HAVE_BUFFER
+#if defined(I915_HAVE_BUFFER) && defined(I915_TTM)
/* i915_buffer.c */
extern struct drm_ttm_backend *i915_create_ttm_backend_entry(struct drm_device *dev);
extern int i915_fence_type(struct drm_buffer_object *bo, uint32_t *fclass,
@@ -495,6 +495,8 @@ extern uint64_t i915_evict_flags(struct drm_buffer_object *bo);
extern int i915_move(struct drm_buffer_object *bo, int evict,
int no_wait, struct drm_bo_mem_reg *new_mem);
void i915_flush_ttm(struct drm_ttm *ttm);
+#endif /* ttm */
+#ifdef I915_HAVE_BUFFER
/* i915_execbuf.c */
int i915_execbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv);
@@ -530,6 +532,9 @@ void i915_gem_retire_requests(struct drm_device *dev);
void i915_gem_retire_timeout(unsigned long data);
void i915_gem_retire_handler(struct work_struct *work);
int i915_gem_init_ringbuffer(struct drm_device *dev);
+void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
+int i915_gem_do_init(struct drm_device *dev, unsigned long start,
+ unsigned long end);
#endif
extern unsigned int i915_fbpercrtc;
@@ -596,12 +601,6 @@ void i915_ring_validate(struct drm_device *dev, const char *func, int line);
I915_WRITE(PRB0_TAIL, outring); \
} while(0)
-#define BREADCRUMB_BITS 31
-#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
-
-#define READ_BREADCRUMB(dev_priv) (((volatile u32*)(dev_priv->hw_status_page))[5])
-#define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg])
-
extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
/*
@@ -713,7 +712,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define BREADCRUMB_BITS 31
#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
-#define READ_BREADCRUMB(dev_priv) (((volatile u32*)(dev_priv->hw_status_page))[5])
+#define READ_BREADCRUMB(dev_priv) (((volatile u32*)(dev_priv->hws_vaddr))[5])
/**
* Reads a dword out of the status page, which is written to from the command
@@ -728,7 +727,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
*
* The area from dword 0x10 to 0x3ff is available for driver usage.
*/
-#define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg])
+#define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hws_vaddr))[reg])
#define I915_GEM_HWS_INDEX 0x10
/*
@@ -986,12 +985,6 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define ADPA_DPMS_STANDBY (2<<10)
#define ADPA_DPMS_OFF (3<<10)
-#define LP_RING 0x2030
-#define HP_RING 0x2040
-/* The binner has its own ring buffer:
- */
-#define HWB_RING 0x2400
-
#define RING_TAIL 0x00
#define TAIL_ADDR 0x001FFFF8
#define RING_HEAD 0x04
diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c
index ba02f485..3f310770 100644
--- a/shared-core/i915_init.c
+++ b/shared-core/i915_init.c
@@ -100,24 +100,11 @@ int i915_probe_agp(struct pci_dev *pdev, unsigned long *aperture_size,
return 0;
}
-int i915_load_modeset_init(struct drm_device *dev)
+static int i915_init_hwstatus(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- unsigned long agp_size, prealloc_size;
- int size, ret = 0;
-
- i915_probe_agp(dev->pdev, &agp_size, &prealloc_size);
- printk("setting up %ld bytes of VRAM space\n", prealloc_size);
- printk("setting up %ld bytes of TT space\n", (agp_size - prealloc_size));
- ret = i915_gem_init_ringbuffer(dev);
- if (ret)
- goto out;
-
- /* Allow hardware batchbuffers unless told otherwise.
- */
- dev_priv->allow_batchbuffer = 1;
- dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS;
- mutex_init(&dev_priv->cmdbuf_mutex);
+ struct drm_memrange_node *free_space;
+ int ret = 0;
/* Program Hardware Status Page */
if (!IS_G33(dev)) {
@@ -127,52 +114,105 @@ int i915_load_modeset_init(struct drm_device *dev)
if (!dev_priv->status_page_dmah) {
DRM_ERROR("Can not allocate hardware status page\n");
ret = -ENOMEM;
- goto destroy_ringbuffer;
+ goto out;
}
- dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+ dev_priv->hws_vaddr = dev_priv->status_page_dmah->vaddr;
dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-
I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
} else {
- size = 4 * 1024;
- ret = drm_buffer_object_create(dev, size,
- drm_bo_type_kernel,
- DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE |
- DRM_BO_FLAG_MEM_VRAM |
- DRM_BO_FLAG_NO_EVICT,
- DRM_BO_HINT_DONT_FENCE, 0x1, 0,
- &dev_priv->hws_bo);
- if (ret < 0) {
+ free_space = drm_memrange_search_free(&dev_priv->vram,
+ PAGE_SIZE,
+ PAGE_SIZE, 0);
+ if (!free_space) {
+ DRM_ERROR("No free vram available, aborting\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ dev_priv->hws = drm_memrange_get_block(free_space, PAGE_SIZE,
+ PAGE_SIZE);
+ if (!dev_priv->hws) {
DRM_ERROR("Unable to allocate or pin hw status page\n");
ret = -EINVAL;
- goto destroy_ringbuffer;
+ goto out;
}
- dev_priv->status_gfx_addr =
- dev_priv->hws_bo->offset & (0x1ffff << 12);
+ dev_priv->hws_agpoffset = dev_priv->hws->start;
dev_priv->hws_map.offset = dev->agp->base +
- dev_priv->hws_bo->offset;
- dev_priv->hws_map.size = size;
+ dev_priv->hws->start;
+ dev_priv->hws_map.size = PAGE_SIZE;
dev_priv->hws_map.type= 0;
dev_priv->hws_map.flags= 0;
dev_priv->hws_map.mtrr = 0;
drm_core_ioremap(&dev_priv->hws_map, dev);
if (dev_priv->hws_map.handle == NULL) {
- dev_priv->status_gfx_addr = 0;
+ dev_priv->hws_agpoffset = 0;
DRM_ERROR("can not ioremap virtual addr for"
"G33 hw status page\n");
ret = -ENOMEM;
- goto destroy_hws;
+ goto out_free;
}
- dev_priv->hw_status_page = dev_priv->hws_map.handle;
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
- I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
+ dev_priv->hws_vaddr = dev_priv->hws_map.handle;
+ I915_WRITE(HWS_PGA, dev_priv->hws_agpoffset);
}
+
+ memset(dev_priv->hws_vaddr, 0, PAGE_SIZE);
+
DRM_DEBUG("Enabled hardware status page\n");
+ return 0;
+
+out_free:
+ /* free hws */
+out:
+ return ret;
+}
+
+static void i915_cleanup_hwstatus(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (!IS_G33(dev)) {
+ if (dev_priv->status_page_dmah)
+ drm_pci_free(dev, dev_priv->status_page_dmah);
+ } else {
+ if (dev_priv->hws_map.handle)
+ drm_core_ioremapfree(&dev_priv->hws_map, dev);
+ if (dev_priv->hws)
+ drm_memrange_put_block(dev_priv->hws);
+ }
+ I915_WRITE(HWS_PGA, 0x1ffff000);
+}
+
+static int i915_load_modeset_init(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned long agp_size, prealloc_size;
+ int ret = 0;
+
+ i915_probe_agp(dev->pdev, &agp_size, &prealloc_size);
+
+ /* Basic memrange allocator for stolen space (aka vram) */
+ drm_memrange_init(&dev_priv->vram, 0, prealloc_size);
+ /* Let GEM Manage from end of prealloc space to end of aperture */
+ i915_gem_do_init(dev, prealloc_size, agp_size);
+
+ ret = i915_gem_init_ringbuffer(dev);
+ if (ret)
+ goto out;
+
+ ret = i915_init_hwstatus(dev);
+ if (ret)
+ goto destroy_ringbuffer;
+
+ /* Allow hardware batchbuffers unless told otherwise.
+ */
+ dev_priv->allow_batchbuffer = 1;
+ dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS;
+ mutex_init(&dev_priv->cmdbuf_mutex);
+
dev_priv->wq = create_singlethread_workqueue("i915");
if (dev_priv->wq == 0) {
DRM_DEBUG("Error\n");
@@ -208,22 +248,9 @@ modeset_cleanup:
destroy_wq:
destroy_workqueue(dev_priv->wq);
destroy_hws:
- if (!IS_G33(dev)) {
- if (dev_priv->status_page_dmah)
- drm_pci_free(dev, dev_priv->status_page_dmah);
- } else {
- if (dev_priv->hws_map.handle)
- drm_core_ioremapfree(&dev_priv->hws_map, dev);
- if (dev_priv->hws_bo)
- drm_bo_usage_deref_unlocked(&dev_priv->hws_bo);
- }
- I915_WRITE(HWS_PGA, 0x1ffff000);
+ i915_cleanup_hwstatus(dev);
destroy_ringbuffer:
- if (dev_priv->ring.virtual_start)
- drm_mem_reg_iounmap(dev, &dev_priv->ring_buffer->mem,
- dev_priv->ring.virtual_start);
- if (dev_priv->ring_buffer)
- drm_bo_usage_deref_unlocked(&dev_priv->ring_buffer);
+ i915_gem_cleanup_ringbuffer(dev);
out:
return ret;
}
@@ -318,26 +345,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
#endif
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- /*
- * Initialize the memory manager for local and AGP space
- */
- ret = drm_bo_driver_init(dev);
- if (ret) {
- DRM_ERROR("fail to init memory manager for "
- "local & AGP space\n");
- goto out_rmmap;
- }
-
ret = i915_load_modeset_init(dev);
if (ret < 0) {
DRM_ERROR("failed to init modeset\n");
- goto driver_fini;
+ goto out_rmmap;
}
}
return 0;
-driver_fini:
- drm_bo_driver_finish(dev);
out_rmmap:
drm_rmmap(dev, dev_priv->mmio_map);
free_priv:
@@ -362,6 +377,8 @@ int i915_driver_unload(struct drm_device *dev)
drm_core_ioremapfree(&dev_priv->ring.map, dev);
}
#endif
+
+#ifdef DRI2
if (dev_priv->sarea_kmap.virtual) {
drm_bo_kunmap(&dev_priv->sarea_kmap);
dev_priv->sarea_kmap.virtual = NULL;
@@ -374,44 +391,17 @@ int i915_driver_unload(struct drm_device *dev)
mutex_unlock(&dev->struct_mutex);
dev_priv->sarea_bo = NULL;
}
-
- if (dev_priv->status_page_dmah) {
- drm_pci_free(dev, dev_priv->status_page_dmah);
- dev_priv->status_page_dmah = NULL;
- dev_priv->hw_status_page = NULL;
- dev_priv->dma_status_page = 0;
- /* Need to rewrite hardware status page */
- I915_WRITE(HWS_PGA, 0x1ffff000);
- }
-
- if (dev_priv->status_gfx_addr) {
- dev_priv->status_gfx_addr = 0;
- drm_core_ioremapfree(&dev_priv->hws_map, dev);
- drm_bo_usage_deref_unlocked(&dev_priv->hws_bo);
- I915_WRITE(HWS_PGA, 0x1ffff000);
- }
+#endif
+ i915_cleanup_hwstatus(dev);
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- drm_mem_reg_iounmap(dev, &dev_priv->ring_buffer->mem,
- dev_priv->ring.virtual_start);
-
- DRM_DEBUG("usage is %d\n", atomic_read(&dev_priv->ring_buffer->usage));
mutex_lock(&dev->struct_mutex);
- drm_bo_usage_deref_locked(&dev_priv->ring_buffer);
-
- if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT, 1)) {
- DRM_ERROR("Memory manager type 3 not clean. "
- "Delaying takedown\n");
- }
- if (drm_bo_clean_mm(dev, DRM_BO_MEM_VRAM, 1)) {
- DRM_ERROR("Memory manager type 3 not clean. "
- "Delaying takedown\n");
- }
+ i915_gem_cleanup_ringbuffer(dev);
mutex_unlock(&dev->struct_mutex);
+ drm_memrange_takedown(&dev_priv->vram);
+ i915_gem_lastclose(dev);
}
- drm_bo_driver_finish(dev);
-
#ifdef __linux__
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
intel_init_chipset_flush_compat(dev);
@@ -493,7 +483,7 @@ void i915_driver_lastclose(struct drm_device * dev)
if (dev_priv->agp_heap)
i915_mem_takedown(&(dev_priv->agp_heap));
-#if defined(I915_HAVE_BUFFER)
+#if defined(DRI2)
if (dev_priv->sarea_kmap.virtual) {
drm_bo_kunmap(&dev_priv->sarea_kmap);
dev_priv->sarea_kmap.virtual = NULL;
@@ -516,7 +506,8 @@ int i915_driver_firstopen(struct drm_device *dev)
{
if (drm_core_check_feature(dev, DRIVER_MODESET))
return 0;
-
+#if defined(I915_HAVE_BUFFER) && defined(I915_TTM)
drm_bo_driver_init(dev);
+#endif
return 0;
}