OSDN Git Service

Use GEM in modesetting
authorJesse Barnes <jbarnes@jbarnes-t61.(none)>
Wed, 11 Jun 2008 22:59:01 +0000 (15:59 -0700)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Wed, 11 Jun 2008 22:59:01 +0000 (15:59 -0700)
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).

linux-core/i915_drv.c
linux-core/i915_gem.c
linux-core/intel_display.c
linux-core/intel_drv.h
linux-core/intel_fb.c
shared-core/i915_dma.c
shared-core/i915_drv.h
shared-core/i915_init.c

index 8718bd1..574282b 100644 (file)
@@ -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,
index 961831c..4774501 100644 (file)
@@ -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;
index 0a2854a..50ad1a2 100644 (file)
@@ -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) {
index 1008e27..bffbeef 100644 (file)
@@ -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;
 };
 
 
index 856ec86..d53b22f 100644 (file)
@@ -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;
index 1e51e70..0cd920d 100644 (file)
@@ -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;
 }
 
index cfb064f..06aa00a 100644 (file)
@@ -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
index ba02f48..3f31077 100644 (file)
@@ -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;
 }