drm/i915: Split the stolen handling for GEM out of i915_dma.c
[deliverable/linux.git] / drivers / gpu / drm / i915 / i915_dma.c
index 785f67f963efd5b53e0a0358e956888b103da5bd..e3f1488b9933a35230fc3dd79a37ec660e0a8885 100644 (file)
@@ -26,6 +26,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "drmP.h"
 #include "drm.h"
 #include "drm_crtc_helper.h"
@@ -43,6 +45,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <acpi/video.h>
+#include <asm/pat.h>
 
 static void i915_write_hws_pga(struct drm_device *dev)
 {
@@ -787,6 +790,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_LLC:
                value = HAS_LLC(dev);
                break;
+       case I915_PARAM_HAS_ALIASING_PPGTT:
+               value = dev_priv->mm.aliasing_ppgtt ? 1 : 0;
+               break;
        default:
                DRM_DEBUG_DRIVER("Unknown parameter %d\n",
                                 param->param);
@@ -1013,133 +1019,6 @@ intel_teardown_mchbar(struct drm_device *dev)
                release_resource(&dev_priv->mch_res);
 }
 
-#define PTE_ADDRESS_MASK               0xfffff000
-#define PTE_ADDRESS_MASK_HIGH          0x000000f0 /* i915+ */
-#define PTE_MAPPING_TYPE_UNCACHED      (0 << 1)
-#define PTE_MAPPING_TYPE_DCACHE                (1 << 1) /* i830 only */
-#define PTE_MAPPING_TYPE_CACHED                (3 << 1)
-#define PTE_MAPPING_TYPE_MASK          (3 << 1)
-#define PTE_VALID                      (1 << 0)
-
-/**
- * i915_stolen_to_phys - take an offset into stolen memory and turn it into
- *                       a physical one
- * @dev: drm device
- * @offset: address to translate
- *
- * Some chip functions require allocations from stolen space and need the
- * physical address of the memory in question.
- */
-static unsigned long i915_stolen_to_phys(struct drm_device *dev, u32 offset)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct pci_dev *pdev = dev_priv->bridge_dev;
-       u32 base;
-
-#if 0
-       /* On the machines I have tested the Graphics Base of Stolen Memory
-        * is unreliable, so compute the base by subtracting the stolen memory
-        * from the Top of Low Usable DRAM which is where the BIOS places
-        * the graphics stolen memory.
-        */
-       if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
-               /* top 32bits are reserved = 0 */
-               pci_read_config_dword(pdev, 0xA4, &base);
-       } else {
-               /* XXX presume 8xx is the same as i915 */
-               pci_bus_read_config_dword(pdev->bus, 2, 0x5C, &base);
-       }
-#else
-       if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
-               u16 val;
-               pci_read_config_word(pdev, 0xb0, &val);
-               base = val >> 4 << 20;
-       } else {
-               u8 val;
-               pci_read_config_byte(pdev, 0x9c, &val);
-               base = val >> 3 << 27;
-       }
-       base -= dev_priv->mm.gtt->stolen_size;
-#endif
-
-       return base + offset;
-}
-
-static void i915_warn_stolen(struct drm_device *dev)
-{
-       DRM_ERROR("not enough stolen space for compressed buffer, disabling\n");
-       DRM_ERROR("hint: you may be able to increase stolen memory size in the BIOS to avoid this\n");
-}
-
-static void i915_setup_compression(struct drm_device *dev, int size)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb);
-       unsigned long cfb_base;
-       unsigned long ll_base = 0;
-
-       /* Just in case the BIOS is doing something questionable. */
-       intel_disable_fbc(dev);
-
-       compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0);
-       if (compressed_fb)
-               compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
-       if (!compressed_fb)
-               goto err;
-
-       cfb_base = i915_stolen_to_phys(dev, compressed_fb->start);
-       if (!cfb_base)
-               goto err_fb;
-
-       if (!(IS_GM45(dev) || HAS_PCH_SPLIT(dev))) {
-               compressed_llb = drm_mm_search_free(&dev_priv->mm.stolen,
-                                                   4096, 4096, 0);
-               if (compressed_llb)
-                       compressed_llb = drm_mm_get_block(compressed_llb,
-                                                         4096, 4096);
-               if (!compressed_llb)
-                       goto err_fb;
-
-               ll_base = i915_stolen_to_phys(dev, compressed_llb->start);
-               if (!ll_base)
-                       goto err_llb;
-       }
-
-       dev_priv->cfb_size = size;
-
-       dev_priv->compressed_fb = compressed_fb;
-       if (HAS_PCH_SPLIT(dev))
-               I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
-       else if (IS_GM45(dev)) {
-               I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
-       } else {
-               I915_WRITE(FBC_CFB_BASE, cfb_base);
-               I915_WRITE(FBC_LL_BASE, ll_base);
-               dev_priv->compressed_llb = compressed_llb;
-       }
-
-       DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n",
-                     cfb_base, ll_base, size >> 20);
-       return;
-
-err_llb:
-       drm_mm_put_block(compressed_llb);
-err_fb:
-       drm_mm_put_block(compressed_fb);
-err:
-       dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
-       i915_warn_stolen(dev);
-}
-
-static void i915_cleanup_compression(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       drm_mm_put_block(dev_priv->compressed_fb);
-       if (dev_priv->compressed_llb)
-               drm_mm_put_block(dev_priv->compressed_llb);
-}
-
 /* true = enable decode, false = disable decoder */
 static unsigned int i915_vga_set_decode(void *cookie, bool state)
 {
@@ -1158,14 +1037,14 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
        struct drm_device *dev = pci_get_drvdata(pdev);
        pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
        if (state == VGA_SWITCHEROO_ON) {
-               printk(KERN_INFO "i915: switched on\n");
+               pr_info("switched on\n");
                dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
                /* i915 resume handler doesn't set to D0 */
                pci_set_power_state(dev->pdev, PCI_D0);
                i915_resume(dev);
                dev->switch_power_state = DRM_SWITCH_POWER_ON;
        } else {
-               printk(KERN_ERR "i915: switched off\n");
+               pr_err("switched off\n");
                dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
                i915_suspend(dev, pmm);
                dev->switch_power_state = DRM_SWITCH_POWER_OFF;
@@ -1201,25 +1080,19 @@ intel_enable_ppgtt(struct drm_device *dev)
 static int i915_load_gem_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long prealloc_size, gtt_size, mappable_size;
+       unsigned long gtt_size, mappable_size;
        int ret;
 
-       prealloc_size = dev_priv->mm.gtt->stolen_size;
        gtt_size = dev_priv->mm.gtt->gtt_total_entries << PAGE_SHIFT;
        mappable_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
 
-       /* Basic memrange allocator for stolen space */
-       drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size);
-
        mutex_lock(&dev->struct_mutex);
        if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) {
                /* PPGTT pdes are stolen from global gtt ptes, so shrink the
                 * aperture accordingly when using aliasing ppgtt. */
                gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
-               /* For paranoia keep the guard page in between. */
-               gtt_size -= PAGE_SIZE;
 
-               i915_gem_do_init(dev, 0, mappable_size, gtt_size);
+               i915_gem_init_global_gtt(dev, 0, mappable_size, gtt_size);
 
                ret = i915_gem_init_aliasing_ppgtt(dev);
                if (ret) {
@@ -1237,7 +1110,8 @@ static int i915_load_gem_init(struct drm_device *dev)
                 * should be enough to keep any prefetching inside of the
                 * aperture.
                 */
-               i915_gem_do_init(dev, 0, mappable_size, gtt_size - PAGE_SIZE);
+               i915_gem_init_global_gtt(dev, 0, mappable_size,
+                                        gtt_size);
        }
 
        ret = i915_gem_init_hw(dev);
@@ -1247,20 +1121,6 @@ static int i915_load_gem_init(struct drm_device *dev)
                return ret;
        }
 
-       /* Try to set up FBC with a reasonable compressed buffer size */
-       if (I915_HAS_FBC(dev) && i915_powersave) {
-               int cfb_size;
-
-               /* Leave 1M for line length buffer & misc. */
-
-               /* Try to get a 32M buffer... */
-               if (prealloc_size > (36*1024*1024))
-                       cfb_size = 32*1024*1024;
-               else /* fall back to 7/8 of the stolen space */
-                       cfb_size = prealloc_size * 7 / 8;
-               i915_setup_compression(dev, cfb_size);
-       }
-
        /* Allow hardware batchbuffers unless told otherwise. */
        dev_priv->allow_batchbuffer = 1;
        return 0;
@@ -1299,11 +1159,18 @@ static int i915_load_modeset_init(struct drm_device *dev)
        if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE))
                dev_priv->flip_pending_is_done = true;
 
+       /* Initialise stolen first so that we may reserve preallocated
+        * objects for the BIOS to KMS transition.
+        */
+       ret = i915_gem_init_stolen(dev);
+       if (ret)
+               goto cleanup_vga_switcheroo;
+
        intel_modeset_init(dev);
 
        ret = i915_load_gem_init(dev);
        if (ret)
-               goto cleanup_vga_switcheroo;
+               goto cleanup_gem_stolen;
 
        intel_modeset_gem_init(dev);
 
@@ -1333,6 +1200,8 @@ cleanup_gem:
        i915_gem_cleanup_ringbuffer(dev);
        mutex_unlock(&dev->struct_mutex);
        i915_gem_cleanup_aliasing_ppgtt(dev);
+cleanup_gem_stolen:
+       i915_gem_cleanup_stolen(dev);
 cleanup_vga_switcheroo:
        vga_switcheroo_unregister_client(dev->pdev);
 cleanup_vga_client:
@@ -1931,6 +1800,29 @@ ips_ping_for_i915_load(void)
        }
 }
 
+static void
+i915_mtrr_setup(struct drm_i915_private *dev_priv, unsigned long base,
+               unsigned long size)
+{
+       dev_priv->mm.gtt_mtrr = -1;
+
+#if defined(CONFIG_X86_PAT)
+       if (cpu_has_pat)
+               return;
+#endif
+
+       /* Set up a WC MTRR for non-PAT systems.  This is more common than
+        * one would think, because the kernel disables PAT on first
+        * generation Core chips because WC PAT gets overridden by a UC
+        * MTRR if present.  Even if a UC MTRR isn't present.
+        */
+       dev_priv->mm.gtt_mtrr = mtrr_add(base, size, MTRR_TYPE_WRCOMB, 1);
+       if (dev_priv->mm.gtt_mtrr < 0) {
+               DRM_INFO("MTRR allocation failed.  Graphics "
+                        "performance may suffer.\n");
+       }
+}
+
 /**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
@@ -1945,8 +1837,16 @@ ips_ping_for_i915_load(void)
 int i915_driver_load(struct drm_device *dev, unsigned long flags)
 {
        struct drm_i915_private *dev_priv;
+       struct intel_device_info *info;
        int ret = 0, mmio_bar;
-       uint32_t agp_size;
+       uint32_t aperture_size;
+
+       info = (struct intel_device_info *) flags;
+
+       /* Refuse to load on gen6+ without kms enabled. */
+       if (info->gen >= 6 && !drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
+
 
        /* i915 has 4 more counters */
        dev->counters += 4;
@@ -1961,7 +1861,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        dev->dev_private = (void *)dev_priv;
        dev_priv->dev = dev;
-       dev_priv->info = (struct intel_device_info *) flags;
+       dev_priv->info = info;
 
        if (i915_get_bridge_dev(dev)) {
                ret = -EIO;
@@ -2000,27 +1900,16 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                goto out_rmmap;
        }
 
-       agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
+       aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
 
        dev_priv->mm.gtt_mapping =
-               io_mapping_create_wc(dev->agp->base, agp_size);
+               io_mapping_create_wc(dev->agp->base, aperture_size);
        if (dev_priv->mm.gtt_mapping == NULL) {
                ret = -EIO;
                goto out_rmmap;
        }
 
-       /* Set up a WC MTRR for non-PAT systems.  This is more common than
-        * one would think, because the kernel disables PAT on first
-        * generation Core chips because WC PAT gets overridden by a UC
-        * MTRR if present.  Even if a UC MTRR isn't present.
-        */
-       dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base,
-                                        agp_size,
-                                        MTRR_TYPE_WRCOMB, 1);
-       if (dev_priv->mm.gtt_mtrr < 0) {
-               DRM_INFO("MTRR allocation failed.  Graphics "
-                        "performance may suffer.\n");
-       }
+       i915_mtrr_setup(dev_priv, dev->agp->base, aperture_size);
 
        /* The i915 workqueue is primarily used for batched retirement of
         * requests (and thus managing bo) once the task has been completed
@@ -2090,7 +1979,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        spin_lock_init(&dev_priv->error_lock);
        spin_lock_init(&dev_priv->rps_lock);
 
-       if (IS_IVYBRIDGE(dev))
+       if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
                dev_priv->num_pipe = 3;
        else if (IS_MOBILE(dev) || !IS_GEN2(dev))
                dev_priv->num_pipe = 2;
@@ -2114,6 +2003,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                }
        }
 
+       i915_setup_sysfs(dev);
+
        /* Must be done after probing outputs */
        intel_opregion_init(dev);
        acpi_video_register();
@@ -2165,6 +2056,8 @@ int i915_driver_unload(struct drm_device *dev)
        i915_mch_dev = NULL;
        spin_unlock(&mchdev_lock);
 
+       i915_teardown_sysfs(dev);
+
        if (dev_priv->mm.inactive_shrinker.shrink)
                unregister_shrinker(&dev_priv->mm.inactive_shrinker);
 
@@ -2223,8 +2116,7 @@ int i915_driver_unload(struct drm_device *dev)
                i915_gem_cleanup_ringbuffer(dev);
                mutex_unlock(&dev->struct_mutex);
                i915_gem_cleanup_aliasing_ppgtt(dev);
-               if (I915_HAS_FBC(dev) && i915_powersave)
-                       i915_cleanup_compression(dev);
+               i915_gem_cleanup_stolen(dev);
                drm_mm_takedown(&dev_priv->mm.stolen);
 
                intel_cleanup_overlay(dev);
@@ -2272,7 +2164,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file)
  * mode setting case, we want to restore the kernel's initial mode (just
  * in case the last client left us in a bad state).
  *
- * Additionally, in the non-mode setting case, we'll tear down the AGP
+ * Additionally, in the non-mode setting case, we'll tear down the GTT
  * and DMA structures, since the kernel won't be using them, and clea
  * up any GEM state.
  */
@@ -2350,16 +2242,10 @@ struct drm_ioctl_desc i915_ioctls[] = {
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
 
-/**
- * Determine if the device really is AGP or not.
- *
- * All Intel graphics chipsets are treated as AGP, even if they are really
- * PCI-e.
- *
- * \param dev   The device to be tested.
- *
- * \returns
- * A value of 1 is always retured to indictate every i9x5 is AGP.
+/*
+ * This is really ugly: Because old userspace abused the linux agp interface to
+ * manage the gtt, we need to claim that all intel devices are agp.  For
+ * otherwise the drm core refuses to initialize the agp support code.
  */
 int i915_driver_device_is_agp(struct drm_device * dev)
 {
This page took 0.030148 seconds and 5 git commands to generate.