diff mbox

drm/i915: Skip unbinding large unmappable global buffers

Message ID 20161013085504.30705-1-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Wilson Oct. 13, 2016, 8:55 a.m. UTC
If the user requests a mappable binding to the global GTT, we will first
unbind an existing mapping if it doesn't match. We will unbind even if
there is no possibility that the object can fit in the mappable
aperture. This may lead to a ping-pong migration of the object, for
example igt/gem_exec_big.

Testcase: igt/gem_exec_big
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

Comments

Saarinen, Jani Oct. 13, 2016, 11:20 a.m. UTC | #1
> == Series Details ==

> 

> Series: drm/i915: Skip unbinding large unmappable global buffers

> URL   : https://patchwork.freedesktop.org/series/13702/

> State : warning

> 

> == Summary ==

> 

> Series 13702v1 drm/i915: Skip unbinding large unmappable global buffers

> https://patchwork.freedesktop.org/api/1.0/series/13702/revisions/1/mbox/

> 

> Test drv_module_reload_basic:

>                 skip       -> PASS       (fi-skl-6260u)

> Test kms_busy:

>         Subgroup basic-flip-default-a:

>                 pass       -> DMESG-WARN (fi-snb-2520m)

dmesg	
[  470.998755] [drm:drm_edid_block_valid] *ERROR* EDID checksum is invalid, remainder is 186
[  470.998762] Raw EDID:
[  470.998765]  	00 ff ff ff ff ff ff 00 04 72 5b 03 63 15 90 34
[  470.998768]  	31 17 01 03 80 35 1e 78 ee a0 a5 a6 56 52 9d 27
[  470.998770]  	0f 50 54 b3 0c 00 71 4f 81 80 81 c0 81 00 95 00
[  470.998772]  	b3 00 d1 c0 01 01 02 3a 80 18 71 38 2d 40 58 2c
[  470.998774]  	45 00 0f 28 21 00 00 1e 00 00 00 fd 00 38 4b 1f
[  470.998776]  	4b 1f ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[  470.998778]  	ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[  470.998779]  	ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

> Test kms_pipe_crc_basic:

>         Subgroup read-crc-pipe-a-frame-sequence:

>                 dmesg-warn -> PASS       (fi-skl-6770hq)

>         Subgroup suspend-read-crc-pipe-a:

>                 dmesg-warn -> PASS       (fi-byt-j1900)

> Test vgem_basic:

>         Subgroup unload:

>                 pass       -> SKIP       (fi-skl-6260u)

>                 pass       -> SKIP       (fi-hsw-4770)

> 

> fi-bdw-5557u     total:246  pass:231  dwarn:0   dfail:0   fail:0   skip:15

> fi-bsw-n3050     total:246  pass:204  dwarn:0   dfail:0   fail:0   skip:42

> fi-bxt-t5700     total:246  pass:216  dwarn:0   dfail:0   fail:0   skip:30

> fi-byt-j1900     total:246  pass:214  dwarn:0   dfail:0   fail:1   skip:31

> fi-byt-n2820     total:246  pass:210  dwarn:0   dfail:0   fail:1   skip:35

> fi-hsw-4770      total:246  pass:223  dwarn:0   dfail:0   fail:0   skip:23

> fi-hsw-4770r     total:246  pass:224  dwarn:0   dfail:0   fail:0   skip:22

> fi-ivb-3520m     total:246  pass:221  dwarn:0   dfail:0   fail:0   skip:25

> fi-ivb-3770      total:246  pass:221  dwarn:0   dfail:0   fail:0   skip:25

> fi-kbl-7200u     total:246  pass:222  dwarn:0   dfail:0   fail:0   skip:24

> fi-skl-6260u     total:246  pass:231  dwarn:0   dfail:0   fail:0   skip:15

> fi-skl-6700hq    total:246  pass:223  dwarn:0   dfail:0   fail:0   skip:23

> fi-skl-6700k     total:246  pass:221  dwarn:1   dfail:0   fail:0   skip:24

> fi-skl-6770hq    total:246  pass:230  dwarn:1   dfail:0   fail:1   skip:14

> fi-snb-2520m     total:246  pass:209  dwarn:1   dfail:0   fail:0   skip:36

> fi-snb-2600      total:246  pass:209  dwarn:0   dfail:0   fail:0   skip:37

> 

> Results at /archive/results/CI_IGT_test/Patchwork_2697/

> 

> d8bf31fcdb62e0b0637352e2e08c95a817f0c543 drm-intel-nightly: 2016y-10m-

> 13d-06h-10m-53s UTC integration manifest

> 825c978 drm/i915: Skip unbinding large unmappable global buffers



Jani Saarinen
Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo
Tvrtko Ursulin Oct. 13, 2016, 11:23 a.m. UTC | #2
On 13/10/2016 12:20, Saarinen, Jani wrote:
>> == Series Details ==
>>
>> Series: drm/i915: Skip unbinding large unmappable global buffers
>> URL   : https://patchwork.freedesktop.org/series/13702/
>> State : warning
>>
>> == Summary ==
>>
>> Series 13702v1 drm/i915: Skip unbinding large unmappable global buffers
>> https://patchwork.freedesktop.org/api/1.0/series/13702/revisions/1/mbox/
>>
>> Test drv_module_reload_basic:
>>                  skip       -> PASS       (fi-skl-6260u)
>> Test kms_busy:
>>          Subgroup basic-flip-default-a:
>>                  pass       -> DMESG-WARN (fi-snb-2520m)
> dmesg	
> [  470.998755] [drm:drm_edid_block_valid] *ERROR* EDID checksum is invalid, remainder is 186
> [  470.998762] Raw EDID:
> [  470.998765]  	00 ff ff ff ff ff ff 00 04 72 5b 03 63 15 90 34
> [  470.998768]  	31 17 01 03 80 35 1e 78 ee a0 a5 a6 56 52 9d 27
> [  470.998770]  	0f 50 54 b3 0c 00 71 4f 81 80 81 c0 81 00 95 00
> [  470.998772]  	b3 00 d1 c0 01 01 02 3a 80 18 71 38 2d 40 58 2c
> [  470.998774]  	45 00 0f 28 21 00 00 1e 00 00 00 fd 00 38 4b 1f
> [  470.998776]  	4b 1f ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [  470.998778]  	ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [  470.998779]  	ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

BZ already exists:

https://bugs.freedesktop.org/show_bug.cgi?id=98228

Regards,

Tvrtko

>> Test kms_pipe_crc_basic:
>>          Subgroup read-crc-pipe-a-frame-sequence:
>>                  dmesg-warn -> PASS       (fi-skl-6770hq)
>>          Subgroup suspend-read-crc-pipe-a:
>>                  dmesg-warn -> PASS       (fi-byt-j1900)
>> Test vgem_basic:
>>          Subgroup unload:
>>                  pass       -> SKIP       (fi-skl-6260u)
>>                  pass       -> SKIP       (fi-hsw-4770)
>>
>> fi-bdw-5557u     total:246  pass:231  dwarn:0   dfail:0   fail:0   skip:15
>> fi-bsw-n3050     total:246  pass:204  dwarn:0   dfail:0   fail:0   skip:42
>> fi-bxt-t5700     total:246  pass:216  dwarn:0   dfail:0   fail:0   skip:30
>> fi-byt-j1900     total:246  pass:214  dwarn:0   dfail:0   fail:1   skip:31
>> fi-byt-n2820     total:246  pass:210  dwarn:0   dfail:0   fail:1   skip:35
>> fi-hsw-4770      total:246  pass:223  dwarn:0   dfail:0   fail:0   skip:23
>> fi-hsw-4770r     total:246  pass:224  dwarn:0   dfail:0   fail:0   skip:22
>> fi-ivb-3520m     total:246  pass:221  dwarn:0   dfail:0   fail:0   skip:25
>> fi-ivb-3770      total:246  pass:221  dwarn:0   dfail:0   fail:0   skip:25
>> fi-kbl-7200u     total:246  pass:222  dwarn:0   dfail:0   fail:0   skip:24
>> fi-skl-6260u     total:246  pass:231  dwarn:0   dfail:0   fail:0   skip:15
>> fi-skl-6700hq    total:246  pass:223  dwarn:0   dfail:0   fail:0   skip:23
>> fi-skl-6700k     total:246  pass:221  dwarn:1   dfail:0   fail:0   skip:24
>> fi-skl-6770hq    total:246  pass:230  dwarn:1   dfail:0   fail:1   skip:14
>> fi-snb-2520m     total:246  pass:209  dwarn:1   dfail:0   fail:0   skip:36
>> fi-snb-2600      total:246  pass:209  dwarn:0   dfail:0   fail:0   skip:37
>>
>> Results at /archive/results/CI_IGT_test/Patchwork_2697/
>>
>> d8bf31fcdb62e0b0637352e2e08c95a817f0c543 drm-intel-nightly: 2016y-10m-
>> 13d-06h-10m-53s UTC integration manifest
>> 825c978 drm/i915: Skip unbinding large unmappable global buffers
>
> Jani Saarinen
> Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo
>
>
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Tvrtko Ursulin Oct. 13, 2016, 11:29 a.m. UTC | #3
On 13/10/2016 09:55, Chris Wilson wrote:
> If the user requests a mappable binding to the global GTT, we will first
> unbind an existing mapping if it doesn't match. We will unbind even if
> there is no possibility that the object can fit in the mappable
> aperture. This may lead to a ping-pong migration of the object, for
> example igt/gem_exec_big.
>
> Testcase: igt/gem_exec_big
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>   drivers/gpu/drm/i915/i915_gem.c | 19 ++++++++++++++++++-
>   1 file changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 2f939f90984b..f33aa9bb95c0 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -3144,6 +3144,9 @@ search_free:
>   
>   			goto err_unpin;
>   		}
> +
> +		GEM_BUG_ON(vma->node.start < start);
> +		GEM_BUG_ON(vma->node.start + vma->node.size > end);
>   	}
>   	GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level));
>   
> @@ -3843,7 +3846,8 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
>   			 u64 alignment,
>   			 u64 flags)
>   {
> -	struct i915_address_space *vm = &to_i915(obj->base.dev)->ggtt.base;
> +	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
> +	struct i915_address_space *vm = &dev_priv->ggtt.base;
>   	struct i915_vma *vma;
>   	int ret;
>   
> @@ -3858,6 +3862,19 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
>   		    (i915_vma_is_pinned(vma) || i915_vma_is_active(vma)))
>   			return ERR_PTR(-ENOSPC);
>   
> +		if (flags & PIN_MAPPABLE) {
> +			u32 fence_size;
> +
> +			fence_size = i915_gem_get_ggtt_size(dev_priv, vma->size,
> +							    i915_gem_object_get_tiling(obj));
> +			if (fence_size > dev_priv->ggtt.mappable_end)
> +				return ERR_PTR(-E2BIG);
> +
> +			if (flags & PIN_NONBLOCK &&
> +			    fence_size > dev_priv->ggtt.mappable_end / 2)
> +				return ERR_PTR(-ENOSPC);

One half of aperture is a magic number or something else?

Regards,

Tvrtko

> +		}
> +
>   		WARN(i915_vma_is_pinned(vma),
>   		     "bo is already pinned in ggtt with incorrect alignment:"
>   		     " offset=%08x, req.alignment=%llx,"
Chris Wilson Oct. 13, 2016, 12:59 p.m. UTC | #4
On Thu, Oct 13, 2016 at 12:29:44PM +0100, Tvrtko Ursulin wrote:
> 
> On 13/10/2016 09:55, Chris Wilson wrote:
> >If the user requests a mappable binding to the global GTT, we will first
> >unbind an existing mapping if it doesn't match. We will unbind even if
> >there is no possibility that the object can fit in the mappable
> >aperture. This may lead to a ping-pong migration of the object, for
> >example igt/gem_exec_big.
> >
> >Testcase: igt/gem_exec_big
> >Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> >---
> >  drivers/gpu/drm/i915/i915_gem.c | 19 ++++++++++++++++++-
> >  1 file changed, 18 insertions(+), 1 deletion(-)
> >
> >diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> >index 2f939f90984b..f33aa9bb95c0 100644
> >--- a/drivers/gpu/drm/i915/i915_gem.c
> >+++ b/drivers/gpu/drm/i915/i915_gem.c
> >@@ -3144,6 +3144,9 @@ search_free:
> >  			goto err_unpin;
> >  		}
> >+
> >+		GEM_BUG_ON(vma->node.start < start);
> >+		GEM_BUG_ON(vma->node.start + vma->node.size > end);
> >  	}
> >  	GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level));
> >@@ -3843,7 +3846,8 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
> >  			 u64 alignment,
> >  			 u64 flags)
> >  {
> >-	struct i915_address_space *vm = &to_i915(obj->base.dev)->ggtt.base;
> >+	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
> >+	struct i915_address_space *vm = &dev_priv->ggtt.base;
> >  	struct i915_vma *vma;
> >  	int ret;
> >@@ -3858,6 +3862,19 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
> >  		    (i915_vma_is_pinned(vma) || i915_vma_is_active(vma)))
> >  			return ERR_PTR(-ENOSPC);
> >+		if (flags & PIN_MAPPABLE) {
> >+			u32 fence_size;
> >+
> >+			fence_size = i915_gem_get_ggtt_size(dev_priv, vma->size,
> >+							    i915_gem_object_get_tiling(obj));
> >+			if (fence_size > dev_priv->ggtt.mappable_end)
> >+				return ERR_PTR(-E2BIG);
> >+
> >+			if (flags & PIN_NONBLOCK &&
> >+			    fence_size > dev_priv->ggtt.mappable_end / 2)
> >+				return ERR_PTR(-ENOSPC);
> 
> One half of aperture is a magic number or something else?

Magic number. NONBLOCK means try, we have a fallback planned.

It more or less comes from the old habit of having to assume that all
fences take up twice the space we expect due to alignment. And given
NONBLOCK means that we should have a better fallback than evicting the
majority of the aperture on a whim.
-Chris
Tvrtko Ursulin Oct. 13, 2016, 2:13 p.m. UTC | #5
On 13/10/2016 13:59, Chris Wilson wrote:
> On Thu, Oct 13, 2016 at 12:29:44PM +0100, Tvrtko Ursulin wrote:
>> On 13/10/2016 09:55, Chris Wilson wrote:
>>> If the user requests a mappable binding to the global GTT, we will first
>>> unbind an existing mapping if it doesn't match. We will unbind even if
>>> there is no possibility that the object can fit in the mappable
>>> aperture. This may lead to a ping-pong migration of the object, for
>>> example igt/gem_exec_big.
>>>
>>> Testcase: igt/gem_exec_big
>>> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
>>> ---
>>>   drivers/gpu/drm/i915/i915_gem.c | 19 ++++++++++++++++++-
>>>   1 file changed, 18 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
>>> index 2f939f90984b..f33aa9bb95c0 100644
>>> --- a/drivers/gpu/drm/i915/i915_gem.c
>>> +++ b/drivers/gpu/drm/i915/i915_gem.c
>>> @@ -3144,6 +3144,9 @@ search_free:
>>>   			goto err_unpin;
>>>   		}
>>> +
>>> +		GEM_BUG_ON(vma->node.start < start);
>>> +		GEM_BUG_ON(vma->node.start + vma->node.size > end);
>>>   	}
>>>   	GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level));
>>> @@ -3843,7 +3846,8 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
>>>   			 u64 alignment,
>>>   			 u64 flags)
>>>   {
>>> -	struct i915_address_space *vm = &to_i915(obj->base.dev)->ggtt.base;
>>> +	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
>>> +	struct i915_address_space *vm = &dev_priv->ggtt.base;
>>>   	struct i915_vma *vma;
>>>   	int ret;
>>> @@ -3858,6 +3862,19 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
>>>   		    (i915_vma_is_pinned(vma) || i915_vma_is_active(vma)))
>>>   			return ERR_PTR(-ENOSPC);
>>> +		if (flags & PIN_MAPPABLE) {
>>> +			u32 fence_size;
>>> +
>>> +			fence_size = i915_gem_get_ggtt_size(dev_priv, vma->size,
>>> +							    i915_gem_object_get_tiling(obj));
>>> +			if (fence_size > dev_priv->ggtt.mappable_end)
>>> +				return ERR_PTR(-E2BIG);
>>> +
>>> +			if (flags & PIN_NONBLOCK &&
>>> +			    fence_size > dev_priv->ggtt.mappable_end / 2)
>>> +				return ERR_PTR(-ENOSPC);
>> One half of aperture is a magic number or something else?
> Magic number. NONBLOCK means try, we have a fallback planned.
>
> It more or less comes from the old habit of having to assume that all
> fences take up twice the space we expect due to alignment. And given
> NONBLOCK means that we should have a better fallback than evicting the
> majority of the aperture on a whim.

Ok I couldn't not think of any potential bad interactions.

If you add a comment explaining the reasoning:

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko
Chris Wilson Oct. 13, 2016, 2:59 p.m. UTC | #6
On Thu, Oct 13, 2016 at 03:13:51PM +0100, Tvrtko Ursulin wrote:
> 
> On 13/10/2016 13:59, Chris Wilson wrote:
> >On Thu, Oct 13, 2016 at 12:29:44PM +0100, Tvrtko Ursulin wrote:
> >>On 13/10/2016 09:55, Chris Wilson wrote:
> >>>If the user requests a mappable binding to the global GTT, we will first
> >>>unbind an existing mapping if it doesn't match. We will unbind even if
> >>>there is no possibility that the object can fit in the mappable
> >>>aperture. This may lead to a ping-pong migration of the object, for
> >>>example igt/gem_exec_big.
> >>>
> >>>Testcase: igt/gem_exec_big
> >>>Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> >>>---
> >>>  drivers/gpu/drm/i915/i915_gem.c | 19 ++++++++++++++++++-
> >>>  1 file changed, 18 insertions(+), 1 deletion(-)
> >>>
> >>>diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> >>>index 2f939f90984b..f33aa9bb95c0 100644
> >>>--- a/drivers/gpu/drm/i915/i915_gem.c
> >>>+++ b/drivers/gpu/drm/i915/i915_gem.c
> >>>@@ -3144,6 +3144,9 @@ search_free:
> >>>  			goto err_unpin;
> >>>  		}
> >>>+
> >>>+		GEM_BUG_ON(vma->node.start < start);
> >>>+		GEM_BUG_ON(vma->node.start + vma->node.size > end);
> >>>  	}
> >>>  	GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level));
> >>>@@ -3843,7 +3846,8 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
> >>>  			 u64 alignment,
> >>>  			 u64 flags)
> >>>  {
> >>>-	struct i915_address_space *vm = &to_i915(obj->base.dev)->ggtt.base;
> >>>+	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
> >>>+	struct i915_address_space *vm = &dev_priv->ggtt.base;
> >>>  	struct i915_vma *vma;
> >>>  	int ret;
> >>>@@ -3858,6 +3862,19 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
> >>>  		    (i915_vma_is_pinned(vma) || i915_vma_is_active(vma)))
> >>>  			return ERR_PTR(-ENOSPC);
> >>>+		if (flags & PIN_MAPPABLE) {
> >>>+			u32 fence_size;
> >>>+
> >>>+			fence_size = i915_gem_get_ggtt_size(dev_priv, vma->size,
> >>>+							    i915_gem_object_get_tiling(obj));
> >>>+			if (fence_size > dev_priv->ggtt.mappable_end)
> >>>+				return ERR_PTR(-E2BIG);
> >>>+
> >>>+			if (flags & PIN_NONBLOCK &&
> >>>+			    fence_size > dev_priv->ggtt.mappable_end / 2)
> >>>+				return ERR_PTR(-ENOSPC);
> >>One half of aperture is a magic number or something else?
> >Magic number. NONBLOCK means try, we have a fallback planned.
> >
> >It more or less comes from the old habit of having to assume that all
> >fences take up twice the space we expect due to alignment. And given
> >NONBLOCK means that we should have a better fallback than evicting the
> >majority of the aperture on a whim.
> 
> Ok I couldn't not think of any potential bad interactions.
> 
> If you add a comment explaining the reasoning:

Felt in the mood to write a few sentences. Hopefully they make sense in
the morning. Thanks,
-Chris
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 2f939f90984b..f33aa9bb95c0 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3144,6 +3144,9 @@  search_free:
 
 			goto err_unpin;
 		}
+
+		GEM_BUG_ON(vma->node.start < start);
+		GEM_BUG_ON(vma->node.start + vma->node.size > end);
 	}
 	GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level));
 
@@ -3843,7 +3846,8 @@  i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
 			 u64 alignment,
 			 u64 flags)
 {
-	struct i915_address_space *vm = &to_i915(obj->base.dev)->ggtt.base;
+	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+	struct i915_address_space *vm = &dev_priv->ggtt.base;
 	struct i915_vma *vma;
 	int ret;
 
@@ -3858,6 +3862,19 @@  i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
 		    (i915_vma_is_pinned(vma) || i915_vma_is_active(vma)))
 			return ERR_PTR(-ENOSPC);
 
+		if (flags & PIN_MAPPABLE) {
+			u32 fence_size;
+
+			fence_size = i915_gem_get_ggtt_size(dev_priv, vma->size,
+							    i915_gem_object_get_tiling(obj));
+			if (fence_size > dev_priv->ggtt.mappable_end)
+				return ERR_PTR(-E2BIG);
+
+			if (flags & PIN_NONBLOCK &&
+			    fence_size > dev_priv->ggtt.mappable_end / 2)
+				return ERR_PTR(-ENOSPC);
+		}
+
 		WARN(i915_vma_is_pinned(vma),
 		     "bo is already pinned in ggtt with incorrect alignment:"
 		     " offset=%08x, req.alignment=%llx,"