Now that we are using struct resource to track the stolen region, it is
more convenient if we track dsm in a resource as well.

v2: check range_overflow when writing to 32b registers (Chris)
    pepper in some comments (Chris)
v3: refit i915_stolen_to_dma()
v4: kill ggtt->stolen_size

Signed-off-by: Matthew Auld <matthew.a...@intel.com>
Cc: Joonas Lahtinen <joonas.lahti...@linux.intel.com>
Cc: Chris Wilson <ch...@chris-wilson.co.uk>
Cc: Paulo Zanoni <paulo.r.zan...@intel.com>
---
 drivers/char/agp/intel-gtt.c           |   2 -
 drivers/gpu/drm/i915/i915_drv.h        |  12 +++-
 drivers/gpu/drm/i915/i915_gem_gtt.c    |   8 +--
 drivers/gpu/drm/i915/i915_gem_gtt.h    |   1 -
 drivers/gpu/drm/i915/i915_gem_stolen.c | 111 +++++++++++++++------------------
 drivers/gpu/drm/i915/intel_fbc.c       |  13 ++--
 drivers/gpu/drm/i915/intel_pm.c        |  15 +++--
 include/drm/intel-gtt.h                |   1 -
 8 files changed, 81 insertions(+), 82 deletions(-)

diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 9b6b6023193b..050708e4562e 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -1422,12 +1422,10 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, 
struct pci_dev *gpu_pdev,
 EXPORT_SYMBOL(intel_gmch_probe);
 
 void intel_gtt_get(u64 *gtt_total,
-                  u32 *stolen_size,
                   phys_addr_t *mappable_base,
                   u64 *mappable_end)
 {
        *gtt_total = intel_private.gtt_total_entries << PAGE_SHIFT;
-       *stolen_size = intel_private.stolen_size;
        *mappable_base = intel_private.gma_bus_addr;
        *mappable_end = intel_private.gtt_mappable_entries << PAGE_SHIFT;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 02551c781f0a..e88fab552278 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1537,9 +1537,6 @@ struct i915_gem_mm {
         */
        struct pagevec wc_stash;
 
-       /** Usable portion of the GTT for GEM */
-       dma_addr_t stolen_base; /* limited to low memory (32-bit) */
-
        /**
         * tmpfs instance used for shmem backed objects
         */
@@ -2253,6 +2250,15 @@ struct drm_i915_private {
 
        const struct intel_device_info info;
 
+       /**
+        * Data Stolen Memory - aka "i915 stolen memory" gives us the start and
+        * end of stolen which we can optionally use to create GEM objects
+        * backed by stolen memory. Note that ggtt->stolen_usable_size tells us
+        * exactly how much of this we are actually allowed to use, given that
+        * some portion of it is in fact reserved for use by hardware functions.
+        */
+       struct resource dsm;
+
        void __iomem *regs;
 
        struct intel_uncore uncore;
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c 
b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 036a79fe252d..62dd90e00c3a 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3299,8 +3299,6 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
 
        pci_read_config_word(pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
 
-       ggtt->stolen_size = resource_size(&intel_graphics_stolen_res);
-
        if (INTEL_GEN(dev_priv) >= 9) {
                size = gen8_get_total_gtt_size(snb_gmch_ctl);
        } else if (IS_CHERRYVIEW(dev_priv)) {
@@ -3363,8 +3361,6 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt)
                DRM_ERROR("Can't set DMA mask/consistent mask (%d)\n", err);
        pci_read_config_word(pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
 
-       ggtt->stolen_size = resource_size(&intel_graphics_stolen_res);
-
        size = gen6_get_total_gtt_size(snb_gmch_ctl);
        ggtt->base.total = (size / sizeof(gen6_pte_t)) << PAGE_SHIFT;
 
@@ -3410,7 +3406,6 @@ static int i915_gmch_probe(struct i915_ggtt *ggtt)
        }
 
        intel_gtt_get(&ggtt->base.total,
-                     &ggtt->stolen_size,
                      &ggtt->mappable_base,
                      &ggtt->mappable_end);
 
@@ -3482,7 +3477,8 @@ int i915_ggtt_probe_hw(struct drm_i915_private *dev_priv)
        DRM_INFO("Memory usable by graphics device = %lluM\n",
                 ggtt->base.total >> 20);
        DRM_DEBUG_DRIVER("GMADR size = %lldM\n", ggtt->mappable_end >> 20);
-       DRM_DEBUG_DRIVER("GTT stolen size = %uM\n", ggtt->stolen_size >> 20);
+       DRM_DEBUG_DRIVER("GTT stolen size = %lluM\n",
+                        (u64)resource_size(&intel_graphics_stolen_res) >> 20);
        if (intel_vtd_active())
                DRM_INFO("VT-d active for gfx access\n");
 
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h 
b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 93211a96fdad..30a2920b1291 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -381,7 +381,6 @@ struct i915_ggtt {
         * avoid the first page! The upper end of stolen memory is reserved for
         * hardware functions and similarly removed from the accessible range.
         */
-       u32 stolen_size;                /* Total size of stolen memory */
        u32 stolen_usable_size; /* Total size minus reserved ranges */
        u32 stolen_reserved_base;
        u32 stolen_reserved_size;
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c 
b/drivers/gpu/drm/i915/i915_gem_stolen.c
index f8ac1438c35d..f2ef5c3788b9 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -76,27 +76,24 @@ void i915_gem_stolen_remove_node(struct drm_i915_private 
*dev_priv,
        mutex_unlock(&dev_priv->mm.stolen_lock);
 }
 
-static dma_addr_t i915_stolen_to_dma(struct drm_i915_private *dev_priv)
+static int i915_adjust_stolen(struct drm_i915_private *dev_priv,
+                             struct resource *dsm)
 {
        struct i915_ggtt *ggtt = &dev_priv->ggtt;
-       dma_addr_t base = intel_graphics_stolen_res.start;
        struct resource *r;
 
-       GEM_BUG_ON(overflows_type(intel_graphics_stolen_res.start, base));
+       if (dsm->start == 0 || add_overflows(dsm->start, resource_size(dsm)))
+               return -EINVAL;
 
-       if (base == 0 || add_overflows(base, ggtt->stolen_size))
-               return 0;
-
-       /* make sure we don't clobber the GTT if it's within stolen memory */
+       /* Make sure we don't clobber the GTT if it's within stolen memory */
        if (INTEL_GEN(dev_priv) <= 4 &&
            !IS_G33(dev_priv) && !IS_PINEVIEW(dev_priv) && !IS_G4X(dev_priv)) {
-               struct {
-                       dma_addr_t start, end;
-               } stolen[2] = {
-                       { .start = base, .end = base + ggtt->stolen_size, },
-                       { .start = base, .end = base + ggtt->stolen_size, },
+               struct resource stolen[2] = {
+                       DEFINE_RES_MEM(dsm->start, resource_size(dsm)),
+                       DEFINE_RES_MEM(dsm->start, resource_size(dsm)),
                };
-               u64 ggtt_start, ggtt_end;
+               struct resource ggtt_res;
+               u64 ggtt_start;
 
                ggtt_start = I915_READ(PGTBL_CTL);
                if (IS_GEN4(dev_priv))
@@ -104,70 +101,63 @@ static dma_addr_t i915_stolen_to_dma(struct 
drm_i915_private *dev_priv)
                                     (ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28;
                else
                        ggtt_start &= PGTBL_ADDRESS_LO_MASK;
-               ggtt_end = ggtt_start + ggtt_total_entries(ggtt) * 4;
 
-               if (ggtt_start >= stolen[0].start && ggtt_start < stolen[0].end)
-                       stolen[0].end = ggtt_start;
-               if (ggtt_end > stolen[1].start && ggtt_end <= stolen[1].end)
-                       stolen[1].start = ggtt_end;
+               ggtt_res =
+                       (struct resource) DEFINE_RES_MEM(ggtt_start,
+                                                        
ggtt_total_entries(ggtt) * 4);
+
+               if (ggtt_res.start >= stolen[0].start && ggtt_res.start < 
stolen[0].end)
+                       stolen[0].end = ggtt_res.start;
+               if (ggtt_res.end > stolen[1].start && ggtt_res.end <= 
stolen[1].end)
+                       stolen[1].start = ggtt_res.end;
 
                /* pick the larger of the two chunks */
-               if (stolen[0].end - stolen[0].start >
-                   stolen[1].end - stolen[1].start) {
-                       base = stolen[0].start;
-                       ggtt->stolen_size = stolen[0].end - stolen[0].start;
-               } else {
-                       base = stolen[1].start;
-                       ggtt->stolen_size = stolen[1].end - stolen[1].start;
-               }
+               if (resource_size(&stolen[0]) > resource_size(&stolen[1]))
+                       *dsm = stolen[0];
+               else
+                       *dsm = stolen[1];
 
                if (stolen[0].start != stolen[1].start ||
                    stolen[0].end != stolen[1].end) {
-                       dma_addr_t end = base + ggtt->stolen_size - 1;
-
-                       DRM_DEBUG_KMS("GTT within stolen memory at 
0x%llx-0x%llx\n",
-                                     (unsigned long long)ggtt_start,
-                                     (unsigned long long)ggtt_end - 1);
-                       DRM_DEBUG_KMS("Stolen memory adjusted to %pad - %pad\n",
-                                     &base, &end);
+                       DRM_DEBUG_KMS("GTT within stolen memory at %pR\n", 
&ggtt_res);
+                       DRM_DEBUG_KMS("Stolen memory adjusted to %pR\n", dsm);
                }
        }
 
-
        /* Verify that nothing else uses this physical address. Stolen
         * memory should be reserved by the BIOS and hidden from the
         * kernel. So if the region is already marked as busy, something
         * is seriously wrong.
         */
-       r = devm_request_mem_region(dev_priv->drm.dev, base, ggtt->stolen_size,
+       r = devm_request_mem_region(dev_priv->drm.dev, dsm->start,
+                                   resource_size(dsm),
                                    "Graphics Stolen Memory");
        if (r == NULL) {
                /*
                 * One more attempt but this time requesting region from
-                * base + 1, as we have seen that this resolves the region
+                * start + 1, as we have seen that this resolves the region
                 * conflict with the PCI Bus.
                 * This is a BIOS w/a: Some BIOS wrap stolen in the root
                 * PCI bus, but have an off-by-one error. Hence retry the
                 * reservation starting from 1 instead of 0.
                 * There's also BIOS with off-by-one on the other end.
                 */
-               r = devm_request_mem_region(dev_priv->drm.dev, base + 1,
-                                           ggtt->stolen_size - 2,
+               r = devm_request_mem_region(dev_priv->drm.dev, dsm->start + 1,
+                                           resource_size(dsm) - 2,
                                            "Graphics Stolen Memory");
                /*
                 * GEN3 firmware likes to smash pci bridges into the stolen
                 * range. Apparently this works.
                 */
                if (r == NULL && !IS_GEN3(dev_priv)) {
-                       dma_addr_t end = base + ggtt->stolen_size;
+                       DRM_ERROR("conflict detected with stolen region: %pR\n",
+                                 dsm);
 
-                       DRM_ERROR("conflict detected with stolen region: [%pad 
- %pad]\n",
-                                 &base, &end);
-                       base = 0;
+                       return -EBUSY;
                }
        }
 
-       return base;
+       return 0;
 }
 
 void i915_gem_cleanup_stolen(struct drm_device *dev)
@@ -183,11 +173,10 @@ void i915_gem_cleanup_stolen(struct drm_device *dev)
 static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv,
                                    dma_addr_t *base, u32 *size)
 {
-       struct i915_ggtt *ggtt = &dev_priv->ggtt;
        uint32_t reg_val = I915_READ(IS_GM45(dev_priv) ?
                                     CTG_STOLEN_RESERVED :
                                     ELK_STOLEN_RESERVED);
-       dma_addr_t stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size;
+       dma_addr_t stolen_top = dev_priv->dsm.end + 1;
 
        if ((reg_val & G4X_STOLEN_RESERVED_ENABLE) == 0) {
                *base = 0;
@@ -308,7 +297,6 @@ static void chv_get_stolen_reserved(struct drm_i915_private 
*dev_priv,
 static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv,
                                    dma_addr_t *base, u32 *size)
 {
-       struct i915_ggtt *ggtt = &dev_priv->ggtt;
        uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED);
        dma_addr_t stolen_top;
 
@@ -318,7 +306,7 @@ static void bdw_get_stolen_reserved(struct drm_i915_private 
*dev_priv,
                return;
        }
 
-       stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size;
+       stolen_top = dev_priv->dsm.end + 1;
 
        *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK;
 
@@ -351,14 +339,18 @@ int i915_gem_init_stolen(struct drm_i915_private 
*dev_priv)
                return 0;
        }
 
-       if (ggtt->stolen_size == 0)
+       if (resource_size(&intel_graphics_stolen_res) == 0)
                return 0;
 
-       dev_priv->mm.stolen_base = i915_stolen_to_dma(dev_priv);
-       if (dev_priv->mm.stolen_base == 0)
+       dev_priv->dsm = intel_graphics_stolen_res;
+
+       if (i915_adjust_stolen(dev_priv, &dev_priv->dsm))
                return 0;
 
-       stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size;
+       GEM_BUG_ON(dev_priv->dsm.start == 0);
+       GEM_BUG_ON(resource_size(&dev_priv->dsm) == 0);
+
+       stolen_top = dev_priv->dsm.end + 1;
        reserved_base = 0;
        reserved_size = 0;
 
@@ -399,12 +391,12 @@ int i915_gem_init_stolen(struct drm_i915_private 
*dev_priv)
                reserved_base = stolen_top;
        }
 
-       if (reserved_base < dev_priv->mm.stolen_base ||
+       if (reserved_base < dev_priv->dsm.start ||
            reserved_base + reserved_size > stolen_top) {
                dma_addr_t reserved_top = reserved_base + reserved_size;
                DRM_ERROR("Stolen reserved area [%pad - %pad] outside stolen 
memory [%pad - %pad]\n",
                          &reserved_base, &reserved_top,
-                         &dev_priv->mm.stolen_base, &stolen_top);
+                         &dev_priv->dsm.start, &stolen_top);
                return 0;
        }
 
@@ -415,9 +407,9 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv)
         * memory, so just consider the start. */
        reserved_total = stolen_top - reserved_base;
 
-       DRM_DEBUG_KMS("Memory reserved for graphics device: %uK, usable: %uK\n",
-                     ggtt->stolen_size >> 10,
-                     (ggtt->stolen_size - reserved_total) >> 10);
+       DRM_DEBUG_KMS("Memory reserved for graphics device: %lluK, usable: 
%lluK\n",
+                     (u64)resource_size(&dev_priv->dsm) >> 10,
+                     ((u64)resource_size(&dev_priv->dsm) - reserved_total) >> 
10);
 
        stolen_usable_start = 0;
        /* WaSkipStolenMemoryFirstPage:bdw+ */
@@ -425,7 +417,7 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv)
                stolen_usable_start = 4096;
 
        ggtt->stolen_usable_size =
-               ggtt->stolen_size - reserved_total - stolen_usable_start;
+               resource_size(&dev_priv->dsm) - reserved_total - 
stolen_usable_start;
 
        /* Basic memrange allocator for stolen space. */
        drm_mm_init(&dev_priv->mm.stolen, stolen_usable_start,
@@ -442,7 +434,8 @@ i915_pages_create_for_stolen(struct drm_device *dev,
        struct sg_table *st;
        struct scatterlist *sg;
 
-       GEM_BUG_ON(range_overflows(offset, size, dev_priv->ggtt.stolen_size));
+       GEM_BUG_ON(range_overflows_t(resource_size_t, offset, size,
+                                    resource_size(&dev_priv->dsm)));
 
        /* We hide that we have no struct page backing our stolen object
         * by wrapping the contiguous physical allocation with a fake
@@ -462,7 +455,7 @@ i915_pages_create_for_stolen(struct drm_device *dev,
        sg->offset = 0;
        sg->length = size;
 
-       sg_dma_address(sg) = (dma_addr_t)dev_priv->mm.stolen_base + offset;
+       sg_dma_address(sg) = (dma_addr_t)dev_priv->dsm.start + offset;
        sg_dma_len(sg) = size;
 
        return st;
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 4aefc658a5cf..f88c1b5dae4c 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -531,7 +531,6 @@ static int find_compression_threshold(struct 
drm_i915_private *dev_priv,
                                      int size,
                                      int fb_cpp)
 {
-       struct i915_ggtt *ggtt = &dev_priv->ggtt;
        int compression_threshold = 1;
        int ret;
        u64 end;
@@ -541,7 +540,7 @@ static int find_compression_threshold(struct 
drm_i915_private *dev_priv,
         * If we enable FBC using a CFB on that memory range we'll get FIFO
         * underruns, even if that range is not reserved by the BIOS. */
        if (IS_BROADWELL(dev_priv) || IS_GEN9_BC(dev_priv))
-               end = ggtt->stolen_size - 8 * 1024 * 1024;
+               end = resource_size(&dev_priv->dsm) - 8 * 1024 * 1024;
        else
                end = U64_MAX;
 
@@ -615,10 +614,16 @@ static int intel_fbc_alloc_cfb(struct intel_crtc *crtc)
 
                fbc->compressed_llb = compressed_llb;
 
+               GEM_BUG_ON(range_overflows_t(u64, dev_priv->dsm.start,
+                                            fbc->compressed_fb.start,
+                                            U32_MAX));
+               GEM_BUG_ON(range_overflows_t(u64, dev_priv->dsm.start,
+                                            fbc->compressed_llb->start,
+                                            U32_MAX));
                I915_WRITE(FBC_CFB_BASE,
-                          dev_priv->mm.stolen_base + fbc->compressed_fb.start);
+                          dev_priv->dsm.start + fbc->compressed_fb.start);
                I915_WRITE(FBC_LL_BASE,
-                          dev_priv->mm.stolen_base + compressed_llb->start);
+                          dev_priv->dsm.start + compressed_llb->start);
        }
 
        DRM_DEBUG_KMS("reserved %llu bytes of contiguous stolen space for FBC, 
threshold: %d\n",
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 5836181d6f8a..79b3fd617de0 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -7020,7 +7020,7 @@ static void valleyview_check_pctx(struct drm_i915_private 
*dev_priv)
 {
        unsigned long pctx_addr = I915_READ(VLV_PCBR) & ~4095;
 
-       WARN_ON(pctx_addr != dev_priv->mm.stolen_base +
+       WARN_ON(pctx_addr != dev_priv->dsm.start +
                             dev_priv->vlv_pctx->stolen->start);
 }
 
@@ -7035,7 +7035,6 @@ static void cherryview_check_pctx(struct drm_i915_private 
*dev_priv)
 
 static void cherryview_setup_pctx(struct drm_i915_private *dev_priv)
 {
-       struct i915_ggtt *ggtt = &dev_priv->ggtt;
        unsigned long pctx_paddr, paddr;
        u32 pcbr;
        int pctx_size = 32*1024;
@@ -7043,8 +7042,8 @@ static void cherryview_setup_pctx(struct drm_i915_private 
*dev_priv)
        pcbr = I915_READ(VLV_PCBR);
        if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) {
                DRM_DEBUG_DRIVER("BIOS didn't set up PCBR, fixing up\n");
-               paddr = (dev_priv->mm.stolen_base +
-                        (ggtt->stolen_size - pctx_size));
+               paddr = dev_priv->dsm.end + 1 - pctx_size;
+               GEM_BUG_ON(paddr > U32_MAX);
 
                pctx_paddr = (paddr & (~4095));
                I915_WRITE(VLV_PCBR, pctx_paddr);
@@ -7065,7 +7064,7 @@ static void valleyview_setup_pctx(struct drm_i915_private 
*dev_priv)
                /* BIOS set it up already, grab the pre-alloc'd space */
                int pcbr_offset;
 
-               pcbr_offset = (pcbr & (~4095)) - dev_priv->mm.stolen_base;
+               pcbr_offset = (pcbr & (~4095)) - dev_priv->dsm.start;
                pctx = i915_gem_object_create_stolen_for_preallocated(dev_priv,
                                                                      
pcbr_offset,
                                                                      
I915_GTT_OFFSET_NONE,
@@ -7089,7 +7088,11 @@ static void valleyview_setup_pctx(struct 
drm_i915_private *dev_priv)
                goto out;
        }
 
-       pctx_paddr = dev_priv->mm.stolen_base + pctx->stolen->start;
+       GEM_BUG_ON(range_overflows_t(u64,
+                                    dev_priv->dsm.start,
+                                    pctx->stolen->start,
+                                    U32_MAX));
+       pctx_paddr = dev_priv->dsm.start + pctx->stolen->start;
        I915_WRITE(VLV_PCBR, pctx_paddr);
 
 out:
diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h
index c5db7975c640..8c577ca38e2e 100644
--- a/include/drm/intel-gtt.h
+++ b/include/drm/intel-gtt.h
@@ -5,7 +5,6 @@
 #define        _DRM_INTEL_GTT_H
 
 void intel_gtt_get(u64 *gtt_total,
-                  u32 *stolen_size,
                   phys_addr_t *mappable_base,
                   u64 *mappable_end);
 
-- 
2.14.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to