drm: fix two issues with fb consolidation.
[safe/jmp/linux-2.6] / drivers / gpu / drm / i915 / i915_dma.c
index 0e704bb..c628c36 100644 (file)
 #include "drmP.h"
 #include "drm.h"
 #include "drm_crtc_helper.h"
+#include "drm_fb_helper.h"
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
 
-#define I915_DRV       "i915_drv"
-
 /* Really want an OS-independent resettable timer.  Would like to have
  * this loop run for (eg) 3 sec, but have the timer reset every time
  * the head pointer changes, so that EBUSY only happens if the ring
@@ -101,7 +100,7 @@ static int i915_init_phys_hws(struct drm_device *dev)
        memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
 
        I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
-       DRM_DEBUG_DRIVER(I915_DRV, "Enabled hardware status page\n");
+       DRM_DEBUG_DRIVER("Enabled hardware status page\n");
        return 0;
 }
 
@@ -187,8 +186,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
                master_priv->sarea_priv = (drm_i915_sarea_t *)
                        ((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
        } else {
-               DRM_DEBUG_DRIVER(I915_DRV,
-                               "sarea not found assuming DRI2 userspace\n");
+               DRM_DEBUG_DRIVER("sarea not found assuming DRI2 userspace\n");
        }
 
        if (init->ring_size != 0) {
@@ -238,7 +236,7 @@ static int i915_dma_resume(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-       DRM_DEBUG_DRIVER(I915_DRV, "%s\n", __func__);
+       DRM_DEBUG_DRIVER("%s\n", __func__);
 
        if (dev_priv->ring.map.handle == NULL) {
                DRM_ERROR("can not ioremap virtual address for"
@@ -251,14 +249,14 @@ static int i915_dma_resume(struct drm_device * dev)
                DRM_ERROR("Can not find hardware status page\n");
                return -EINVAL;
        }
-       DRM_DEBUG_DRIVER(I915_DRV, "hw status page @ %p\n",
+       DRM_DEBUG_DRIVER("hw status page @ %p\n",
                                dev_priv->hw_status_page);
 
        if (dev_priv->status_gfx_addr != 0)
                I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
        else
                I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
-       DRM_DEBUG_DRIVER(I915_DRV, "Enabled hardware status page\n");
+       DRM_DEBUG_DRIVER("Enabled hardware status page\n");
 
        return 0;
 }
@@ -552,7 +550,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
        if (!master_priv->sarea_priv)
                return -EINVAL;
 
-       DRM_DEBUG_DRIVER(I915_DRV, "%s: page=%d pfCurrentPage=%d\n",
+       DRM_DEBUG_DRIVER("%s: page=%d pfCurrentPage=%d\n",
                          __func__,
                         dev_priv->current_page,
                         master_priv->sarea_priv->pf_current_page);
@@ -633,8 +631,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
-       DRM_DEBUG_DRIVER(I915_DRV,
-                       "i915 batchbuffer, start %x used %d cliprects %d\n",
+       DRM_DEBUG_DRIVER("i915 batchbuffer, start %x used %d cliprects %d\n",
                        batch->start, batch->used, batch->num_cliprects);
 
        RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
@@ -681,8 +678,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
        void *batch_data;
        int ret;
 
-       DRM_DEBUG_DRIVER(I915_DRV,
-                       "i915 cmdbuffer, buf %p sz %d cliprects %d\n",
+       DRM_DEBUG_DRIVER("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
                        cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
 
        RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
@@ -735,7 +731,7 @@ static int i915_flip_bufs(struct drm_device *dev, void *data,
 {
        int ret;
 
-       DRM_DEBUG_DRIVER(I915_DRV, "%s\n", __func__);
+       DRM_DEBUG_DRIVER("%s\n", __func__);
 
        RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
 
@@ -778,7 +774,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
                value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
                break;
        default:
-               DRM_DEBUG_DRIVER(I915_DRV, "Unknown parameter %d\n",
+               DRM_DEBUG_DRIVER("Unknown parameter %d\n",
                                        param->param);
                return -EINVAL;
        }
@@ -819,7 +815,7 @@ static int i915_setparam(struct drm_device *dev, void *data,
                dev_priv->fence_reg_start = param->value;
                break;
        default:
-               DRM_DEBUG_DRIVER(I915_DRV, "unknown parameter %d\n",
+               DRM_DEBUG_DRIVER("unknown parameter %d\n",
                                        param->param);
                return -EINVAL;
        }
@@ -846,7 +842,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
                return 0;
        }
 
-       DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr);
+       DRM_DEBUG_DRIVER("set status page addr 0x%08x\n", (u32)hws->addr);
 
        dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
 
@@ -868,9 +864,9 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
 
        memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
        I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
-       DRM_DEBUG_DRIVER(I915_DRV, "load hws HWS_PGA with gfx mem 0x%x\n",
+       DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n",
                                dev_priv->status_gfx_addr);
-       DRM_DEBUG_DRIVER(I915_DRV, "load hws at %p\n",
+       DRM_DEBUG_DRIVER("load hws at %p\n",
                                dev_priv->hw_status_page);
        return 0;
 }
@@ -885,8 +881,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
  * some RAM for the framebuffer at early boot.  This code figures out
  * how much was set aside so we can use it for our own purposes.
  */
-static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size,
-                         unsigned long *preallocated_size)
+static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
+                         uint32_t *preallocated_size)
 {
        struct pci_dev *bridge_dev;
        u16 tmp = 0;
@@ -984,10 +980,11 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size,
        return 0;
 }
 
-static int i915_load_modeset_init(struct drm_device *dev)
+static int i915_load_modeset_init(struct drm_device *dev,
+                                 unsigned long prealloc_size,
+                                 unsigned long agp_size)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long agp_size, prealloc_size;
        int fb_bar = IS_I9XX(dev) ? 2 : 0;
        int ret = 0;
 
@@ -1002,10 +999,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
        if (IS_I965G(dev) || IS_G33(dev))
                dev_priv->cursor_needs_physical = false;
 
-       ret = i915_probe_agp(dev, &agp_size, &prealloc_size);
-       if (ret)
-               goto out;
-
        /* Basic memrange allocator for stolen space (aka vram) */
        drm_mm_init(&dev_priv->vram, 0, prealloc_size);
 
@@ -1136,6 +1129,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        struct drm_i915_private *dev_priv = dev->dev_private;
        resource_size_t base, size;
        int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
+       uint32_t agp_size, prealloc_size;
 
        /* i915 has 4 more counters */
        dev->counters += 4;
@@ -1184,9 +1178,29 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                         "performance may suffer.\n");
        }
 
+       ret = i915_probe_agp(dev, &agp_size, &prealloc_size);
+       if (ret)
+               goto out_iomapfree;
+
+       dev_priv->wq = create_workqueue("i915");
+       if (dev_priv->wq == NULL) {
+               DRM_ERROR("Failed to create our workqueue.\n");
+               ret = -ENOMEM;
+               goto out_iomapfree;
+       }
+
        /* enable GEM by default */
        dev_priv->has_gem = 1;
 
+       if (prealloc_size > agp_size * 3 / 4) {
+               DRM_ERROR("Detected broken video BIOS with %d/%dkB of video "
+                         "memory stolen.\n",
+                         prealloc_size / 1024, agp_size / 1024);
+               DRM_ERROR("Disabling GEM. (try reducing stolen memory or "
+                         "updating the BIOS to fix).\n");
+               dev_priv->has_gem = 0;
+       }
+
        dev->driver->get_vblank_counter = i915_get_vblank_counter;
        dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
        if (IS_G4X(dev) || IS_IGDNG(dev)) {
@@ -1200,7 +1214,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (!I915_NEED_GFX_HWS(dev)) {
                ret = i915_init_phys_hws(dev);
                if (ret != 0)
-                       goto out_iomapfree;
+                       goto out_workqueue_free;
        }
 
        i915_get_mem_freq(dev);
@@ -1231,10 +1245,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        }
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               ret = i915_load_modeset_init(dev);
+               ret = i915_load_modeset_init(dev, prealloc_size, agp_size);
                if (ret < 0) {
                        DRM_ERROR("failed to init modeset\n");
-                       goto out_rmmap;
+                       goto out_workqueue_free;
                }
        }
 
@@ -1245,6 +1259,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        return 0;
 
+out_workqueue_free:
+       destroy_workqueue(dev_priv->wq);
 out_iomapfree:
        io_mapping_free(dev_priv->mm.gtt_mapping);
 out_rmmap:
@@ -1258,6 +1274,8 @@ int i915_driver_unload(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       destroy_workqueue(dev_priv->wq);
+
        io_mapping_free(dev_priv->mm.gtt_mapping);
        if (dev_priv->mm.gtt_mtrr >= 0) {
                mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
@@ -1299,7 +1317,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
 {
        struct drm_i915_file_private *i915_file_priv;
 
-       DRM_DEBUG_DRIVER(I915_DRV, "\n");
+       DRM_DEBUG_DRIVER("\n");
        i915_file_priv = (struct drm_i915_file_private *)
            kmalloc(sizeof(*i915_file_priv), GFP_KERNEL);
 
@@ -1330,7 +1348,7 @@ void i915_driver_lastclose(struct drm_device * dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
 
        if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
-               intelfb_restore();
+               drm_fb_helper_restore();
                return;
        }