summaryrefslogtreecommitdiff
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
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).
-rw-r--r--linux-core/i915_drv.c10
-rw-r--r--linux-core/i915_gem.c52
-rw-r--r--linux-core/intel_display.c34
-rw-r--r--linux-core/intel_drv.h3
-rw-r--r--linux-core/intel_fb.c79
-rw-r--r--shared-core/i915_dma.c39
-rw-r--r--shared-core/i915_drv.h41
-rw-r--r--shared-core/i915_init.c193
8 files changed, 231 insertions, 220 deletions
diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c
index 8718bd10..574282b2 100644
--- a/linux-core/i915_drv.c
+++ b/linux-core/i915_drv.c
@@ -48,11 +48,11 @@ module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
unsigned int i915_rightof = 1;
module_param_named(i915_rightof, i915_rightof, int, 0400);
-#ifdef I915_HAVE_FENCE
+#if defined(I915_HAVE_FENCE) && defined(I915_TTM)
extern struct drm_fence_driver i915_fence_driver;
#endif
-#ifdef I915_HAVE_BUFFER
+#if defined(I915_HAVE_BUFFER) && defined(I915_TTM)
static uint32_t i915_mem_prios[] = {DRM_BO_MEM_VRAM, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL};
static uint32_t i915_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_VRAM, DRM_BO_MEM_LOCAL};
@@ -71,7 +71,7 @@ static struct drm_bo_driver i915_bo_driver = {
.ttm_cache_flush = i915_flush_ttm,
.command_stream_barrier = NULL,
};
-#endif
+#endif /* ttm */
static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
{
@@ -619,10 +619,10 @@ static struct drm_driver driver = {
.probe = probe,
.remove = __devexit_p(drm_cleanup_pci),
},
-#ifdef I915_HAVE_FENCE
+#if defined(I915_HAVE_FENCE) && defined(I915_TTM)
.fence_driver = &i915_fence_driver,
#endif
-#ifdef I915_HAVE_BUFFER
+#if defined(I915_HAVE_BUFFER) && defined(I915_TTM)
.bo_driver = &i915_bo_driver,
#endif
.name = DRIVER_NAME,
diff --git a/linux-core/i915_gem.c b/linux-core/i915_gem.c
index 961831c6..47745010 100644
--- a/linux-core/i915_gem.c
+++ b/linux-core/i915_gem.c
@@ -41,28 +41,35 @@ i915_gem_object_set_domain(struct drm_gem_object *obj,
uint32_t read_domains,
uint32_t write_domain);
-int
-i915_gem_init_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+int i915_gem_do_init(struct drm_device *dev, unsigned long start,
+ unsigned long end)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_i915_gem_init *args = data;
-
- mutex_lock(&dev->struct_mutex);
- if (args->gtt_start >= args->gtt_end ||
- (args->gtt_start & (PAGE_SIZE - 1)) != 0 ||
- (args->gtt_end & (PAGE_SIZE - 1)) != 0) {
- mutex_unlock(&dev->struct_mutex);
+ if (start >= end ||
+ (start & (PAGE_SIZE - 1)) != 0 ||
+ (end & (PAGE_SIZE - 1)) != 0) {
return -EINVAL;
}
- drm_memrange_init(&dev_priv->mm.gtt_space, args->gtt_start,
- args->gtt_end - args->gtt_start);
+ drm_memrange_init(&dev_priv->mm.gtt_space, start,
+ end - start);
+
+ return 0;
+}
+
+int
+i915_gem_init_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_init *args = data;
+ int ret;
+ mutex_lock(&dev->struct_mutex);
+ ret = i915_gem_do_init(dev, args->gtt_start, args->gtt_end);
mutex_unlock(&dev->struct_mutex);
- return 0;
+ return ret;
}
static void
@@ -1834,17 +1841,16 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
/* Stop the ring if it's running. */
- I915_WRITE(LP_RING + RING_LEN, 0);
- I915_WRITE(LP_RING + RING_HEAD, 0);
- I915_WRITE(LP_RING + RING_TAIL, 0);
- I915_WRITE(LP_RING + RING_START, 0);
+ I915_WRITE(PRB0_CTL, 0);
+ I915_WRITE(PRB0_HEAD, 0);
+ I915_WRITE(PRB0_TAIL, 0);
+ I915_WRITE(PRB0_START, 0);
/* Initialize the ring. */
- I915_WRITE(LP_RING + RING_START, obj_priv->gtt_offset);
- I915_WRITE(LP_RING + RING_LEN,
- ((obj->size - 4096) & RING_NR_PAGES) |
- RING_NO_REPORT |
- RING_VALID);
+ I915_WRITE(PRB0_START, obj_priv->gtt_offset);
+ I915_WRITE(PRB0_CTL, (((obj->size - 4096) & RING_NR_PAGES) |
+ RING_NO_REPORT |
+ RING_VALID));
/* Update our cache of the ring state */
i915_kernel_lost_context(dev);
@@ -1852,7 +1858,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
return 0;
}
-static void
+void
i915_gem_cleanup_ringbuffer(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c
index 0a2854a2..50ad1a27 100644
--- a/linux-core/intel_display.c
+++ b/linux-core/intel_display.c
@@ -369,6 +369,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)
struct drm_i915_master_private *master_priv;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_framebuffer *intel_fb;
+ struct drm_i915_gem_object *obj_priv;
int pipe = intel_crtc->pipe;
unsigned long Start, Offset;
int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR);
@@ -385,7 +386,9 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)
intel_fb = to_intel_framebuffer(crtc->fb);
- Start = intel_fb->bo->offset;
+ obj_priv = intel_fb->obj->driver_private;
+
+ Start = obj_priv->gtt_offset;
Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
I915_WRITE(dspstride, crtc->fb->pitch);
@@ -1493,7 +1496,7 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = {
};
struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev,
- struct drm_file *file_priv,
+ struct drm_file *filp,
struct drm_mode_fb_cmd *mode_cmd)
{
struct intel_framebuffer *intel_fb;
@@ -1505,15 +1508,15 @@ struct drm_framebuffer *intel_user_framebuffer_create(struct drm_device *dev,
drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
- if (file_priv) {
- mutex_lock(&dev->struct_mutex);
- intel_fb->bo = drm_lookup_buffer_object(file_priv, intel_fb->base.mm_handle, 0);
- mutex_unlock(&dev->struct_mutex);
- if (!intel_fb->bo) {
+ if (filp) {
+ intel_fb->obj = drm_gem_object_lookup(dev, filp,
+ mode_cmd->handle);
+ if (!intel_fb->obj) {
kfree(intel_fb);
return NULL;
}
}
+ drm_gem_object_unreference(intel_fb->obj);
return &intel_fb->base;
}
@@ -1521,22 +1524,25 @@ static int intel_insert_new_fb(struct drm_device *dev, struct drm_file *file_pri
struct drm_framebuffer *fb, struct drm_mode_fb_cmd *mode_cmd)
{
struct intel_framebuffer *intel_fb;
- struct drm_buffer_object *bo;
+ struct drm_gem_object *obj;
struct drm_crtc *crtc;
intel_fb = to_intel_framebuffer(fb);
mutex_lock(&dev->struct_mutex);
- bo = drm_lookup_buffer_object(file_priv, mode_cmd->handle, 0);
- mutex_unlock(&dev->struct_mutex);
+ obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
- if (!bo)
+ if (!obj) {
+ mutex_unlock(&dev->struct_mutex);
return -EINVAL;
+ }
drm_helper_mode_fill_fb_struct(fb, mode_cmd);
-
- drm_bo_usage_deref_unlocked(&intel_fb->bo);
- intel_fb->bo = bo;
+ drm_gem_object_unreference(intel_fb->obj);
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+
+ intel_fb->obj = obj;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
if (crtc->fb == fb) {
diff --git a/linux-core/intel_drv.h b/linux-core/intel_drv.h
index 1008e271..bffbeef0 100644
--- a/linux-core/intel_drv.h
+++ b/linux-core/intel_drv.h
@@ -50,8 +50,7 @@ struct intel_i2c_chan {
struct intel_framebuffer {
struct drm_framebuffer base;
- struct drm_buffer_object *bo;
- struct drm_bo_kmap_obj kmap;
+ struct drm_gem_object *obj;
};
diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c
index 856ec868..d53b22ff 100644
--- a/linux-core/intel_fb.c
+++ b/linux-core/intel_fb.c
@@ -590,9 +590,10 @@ int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height
struct drm_framebuffer *fb;
struct intel_framebuffer *intel_fb;
struct drm_mode_fb_cmd mode_cmd;
- struct drm_buffer_object *fbo = NULL;
+ struct drm_gem_object *fbo = NULL;
+ struct drm_i915_gem_object *obj_priv;
struct device *device = &dev->pdev->dev;
- int ret;
+ int size, aligned_size, ret;
mode_cmd.width = surface_width;/* crtc->desired_mode->hdisplay; */
mode_cmd.height = surface_height;/* crtc->desired_mode->vdisplay; */
@@ -601,26 +602,28 @@ int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height
mode_cmd.pitch = mode_cmd.width * ((mode_cmd.bpp + 1) / 8);
mode_cmd.depth = 24;
- ret = drm_buffer_object_create(dev, mode_cmd.pitch * mode_cmd.height,
- drm_bo_type_kernel,
- DRM_BO_FLAG_READ |
- DRM_BO_FLAG_WRITE |
- DRM_BO_FLAG_MEM_TT |
- DRM_BO_FLAG_MEM_VRAM |
- DRM_BO_FLAG_NO_EVICT,
- DRM_BO_HINT_DONT_FENCE, 0, 0,
- &fbo);
- if (ret || !fbo) {
+ size = mode_cmd.pitch * mode_cmd.height;
+ aligned_size = ALIGN(size, PAGE_SIZE);
+ fbo = drm_gem_object_alloc(dev, aligned_size);
+ if (!fbo) {
printk(KERN_ERR "failed to allocate framebuffer\n");
- return -EINVAL;
+ ret = -ENOMEM;
+ goto out;
+ }
+ obj_priv = fbo->driver_private;
+
+ mutex_lock(&dev->struct_mutex);
+ ret = i915_gem_object_pin(fbo, PAGE_SIZE);
+ if (ret) {
+ DRM_ERROR("failed to pin fb: %d\n", ret);
+ goto out_unref;
}
-
fb = intel_user_framebuffer_create(dev, NULL, &mode_cmd);
if (!fb) {
- drm_bo_usage_deref_unlocked(&fbo);
DRM_ERROR("failed to allocate fb.\n");
- return -EINVAL;
+ ret = -ENOMEM;
+ goto out_unref;
}
list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list);
@@ -628,11 +631,13 @@ int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height
intel_fb = to_intel_framebuffer(fb);
*intel_fb_p = intel_fb;
- intel_fb->bo = fbo;
+ intel_fb->obj = fbo;
info = framebuffer_alloc(sizeof(struct intelfb_par), device);
- if (!info)
- return -EINVAL;
+ if (!info) {
+ ret = -ENOMEM;
+ goto out_unref;
+ }
par = info->par;
@@ -651,19 +656,20 @@ int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height
info->fbops = &intelfb_ops;
info->fix.line_length = fb->pitch;
- info->fix.smem_start = intel_fb->bo->offset + dev->mode_config.fb_base;
- info->fix.smem_len = info->fix.line_length * fb->height;
+ info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset;
+ info->fix.smem_len = size;
info->flags = FBINFO_DEFAULT;
- ret = drm_bo_kmap(intel_fb->bo, 0, intel_fb->bo->num_pages, &intel_fb->kmap);
- if (ret)
- DRM_ERROR("error mapping fb: %d\n", ret);
-
- info->screen_base = intel_fb->kmap.virtual;
- info->screen_size = info->fix.smem_len; /* FIXME */
+ info->screen_base = ioremap(dev->agp->base + obj_priv->gtt_offset,
+ size);
+ if (!info->screen_base) {
+ ret = -ENOSPC;
+ goto out_unref;
+ }
+ info->screen_size = size;
- memset(intel_fb->kmap.virtual, 0, info->screen_size);
+ memset(info->screen_base, 0, size);
info->pseudo_palette = fb->pseudo_palette;
info->var.xres_virtual = fb->width;
@@ -754,10 +760,17 @@ int intelfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height
par->dev = dev;
/* To allow resizeing without swapping buffers */
- printk("allocated %dx%d fb: 0x%08lx, bo %p\n", intel_fb->base.width,
- intel_fb->base.height, intel_fb->bo->offset, fbo);
+ printk("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width,
+ intel_fb->base.height, obj_priv->gtt_offset, fbo);
+ mutex_unlock(&dev->struct_mutex);
return 0;
+
+out_unref:
+ drm_gem_object_unreference(fbo);
+ mutex_unlock(&dev->struct_mutex);
+out:
+ return ret;
}
static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc *crtc)
@@ -1001,8 +1014,10 @@ int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
if (info) {
unregister_framebuffer(info);
- drm_bo_kunmap(&intel_fb->kmap);
- drm_bo_usage_deref_unlocked(&intel_fb->bo);
+ iounmap(info->screen_base);
+ mutex_lock(&dev->struct_mutex);
+ drm_gem_object_unreference(intel_fb->obj);
+ mutex_unlock(&dev->struct_mutex);
framebuffer_release(info);
}
return 0;
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;
}