[Intel-gfx] [PATCH 07/10] drm/i915: Add support for stealing purgable stolen pages

2016-03-19 Thread ankitprasad . r . sharma
From: Chris Wilson 

If we run out of stolen memory when trying to allocate an object, see if
we can reap enough purgeable objects to free up enough contiguous free
space for the allocation. This is in principle very much like evicting
objects to free up enough contiguous space in the vma when binding
a new object - and you will be forgiven for thinking that the code looks
very similar.

At the moment, we do not allow userspace to allocate objects in stolen,
so there is neither the memory pressure to trigger stolen eviction nor
any purgeable objects inside the stolen arena. However, this will change
in the near future, and so better management and defragmentation of
stolen memory will become a real issue.

v2: Remember to remove the drm_mm_node.

v3: Rebased to the latest drm-intel-nightly (Ankit)

v4: corrected if-else braces format (Tvrtko/kerneldoc)

v5: Rebased to the latest drm-intel-nightly (Ankit)
Added a seperate list to maintain purgable objects from stolen memory
region (Chris/Daniel)

v6: Compiler optimization (merging 2 single loops into one for() loop),
corrected code for object eviction, retire_requests before starting
object eviction (Chris)

v7: Added kernel doc for i915_gem_object_create_stolen()

v8: Check for struct_mutex lock before creating object from stolen
region (Tvrtko)

v9: Renamed variables to make usage clear, added comment, removed onetime
used macro (Tvrtko)

v10: Avoid masking of error when stolen_alloc fails (Tvrtko)

v11: Renamed stolen_link to tmp_link, as it may be used for other
purposes too (Chris)
Used ERR_CAST to cast error pointers while returning

v12: Added lockdep_assert before starting stolen-backed object
eviction (Chris)

v13: Rebased

Testcase: igt/gem_stolen

Signed-off-by: Chris Wilson 
Signed-off-by: Ankitprasad Sharma 
Reviewed-by: Tvrtko Ursulin 
---
 drivers/gpu/drm/i915/i915_debugfs.c|   6 +-
 drivers/gpu/drm/i915/i915_drv.h|  17 +++-
 drivers/gpu/drm/i915/i915_gem.c|  15 +++
 drivers/gpu/drm/i915/i915_gem_stolen.c | 171 +
 drivers/gpu/drm/i915/intel_pm.c|   4 +-
 5 files changed, 188 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index ccdca2c..300ce9c 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -172,7 +172,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object 
*obj)
seq_puts(m, ")");
}
if (obj->stolen)
-   seq_printf(m, " (stolen: %08llx)", obj->stolen->start);
+   seq_printf(m, " (stolen: %08llx)", obj->stolen->base.start);
if (obj->pin_display || obj->fault_mappable) {
char s[3], *t = s;
if (obj->pin_display)
@@ -251,9 +251,9 @@ static int obj_rank_by_stolen(void *priv,
struct drm_i915_gem_object *b =
container_of(B, struct drm_i915_gem_object, obj_exec_link);
 
-   if (a->stolen->start < b->stolen->start)
+   if (a->stolen->base.start < b->stolen->base.start)
return -1;
-   if (a->stolen->start > b->stolen->start)
+   if (a->stolen->base.start > b->stolen->base.start)
return 1;
return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ea87a89..4c81828 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -796,6 +796,12 @@ struct i915_ctx_hang_stats {
bool banned;
 };
 
+struct i915_stolen_node {
+   struct drm_mm_node base;
+   struct list_head mm_link;
+   struct drm_i915_gem_object *obj;
+};
+
 /* This must match up with the value previously used for execbuf2.rsvd1. */
 #define DEFAULT_CONTEXT_HANDLE 0
 
@@ -1243,6 +1249,13 @@ struct i915_gem_mm {
 */
struct list_head unbound_list;
 
+   /**
+* List of stolen objects that have been marked as purgeable and
+* thus available for reaping if we need more space for a new
+* allocation. Ordered by time of marking purgeable.
+*/
+   struct list_head stolen_list;
+
/** Usable portion of the GTT for GEM */
unsigned long stolen_base; /* limited to low memory (32-bit) */
 
@@ -2053,7 +2066,7 @@ struct drm_i915_gem_object {
struct list_head vma_list;
 
/** Stolen memory for this object, instead of being backed by shmem. */
-   struct drm_mm_node *stolen;
+   struct i915_stolen_node *stolen;
struct list_head global_list;
 
struct list_head engine_list[I915_NUM_ENGINES];
@@ -2061,6 +2074,8 @@ struct drm_i915_gem_object {
struct list_head obj_exec_link;
 
struct list_head batch_pool_link;
+   /** Used to link an object to a list temporarily */
+   struct list_head tmp_link;
 
/**
 * This is set if the object is on the active lists (has pending
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i9

[Intel-gfx] [PATCH 07/10] drm/i915: Add support for stealing purgable stolen pages

2016-02-29 Thread ankitprasad . r . sharma
From: Chris Wilson 

If we run out of stolen memory when trying to allocate an object, see if
we can reap enough purgeable objects to free up enough contiguous free
space for the allocation. This is in principle very much like evicting
objects to free up enough contiguous space in the vma when binding
a new object - and you will be forgiven for thinking that the code looks
very similar.

At the moment, we do not allow userspace to allocate objects in stolen,
so there is neither the memory pressure to trigger stolen eviction nor
any purgeable objects inside the stolen arena. However, this will change
in the near future, and so better management and defragmentation of
stolen memory will become a real issue.

v2: Remember to remove the drm_mm_node.

v3: Rebased to the latest drm-intel-nightly (Ankit)

v4: corrected if-else braces format (Tvrtko/kerneldoc)

v5: Rebased to the latest drm-intel-nightly (Ankit)
Added a seperate list to maintain purgable objects from stolen memory
region (Chris/Daniel)

v6: Compiler optimization (merging 2 single loops into one for() loop),
corrected code for object eviction, retire_requests before starting
object eviction (Chris)

v7: Added kernel doc for i915_gem_object_create_stolen()

v8: Check for struct_mutex lock before creating object from stolen
region (Tvrtko)

v9: Renamed variables to make usage clear, added comment, removed onetime
used macro (Tvrtko)

v10: Avoid masking of error when stolen_alloc fails (Tvrtko)

v11: Renamed stolen_link to tmp_link, as it may be used for other
purposes too (Chris)
Used ERR_CAST to cast error pointers while returning

v12: Added lockdep_assert before starting stolen-backed object
eviction (Chris)

v13: Rebased

Testcase: igt/gem_stolen

Signed-off-by: Chris Wilson 
Signed-off-by: Ankitprasad Sharma 
Reviewed-by: Tvrtko Ursulin 
---
 drivers/gpu/drm/i915/i915_debugfs.c|   6 +-
 drivers/gpu/drm/i915/i915_drv.h|  17 +++-
 drivers/gpu/drm/i915/i915_gem.c|  15 +++
 drivers/gpu/drm/i915/i915_gem_stolen.c | 171 +
 drivers/gpu/drm/i915/intel_pm.c|   4 +-
 5 files changed, 188 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index a0f1bd7..eb07875 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -172,7 +172,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object 
*obj)
seq_puts(m, ")");
}
if (obj->stolen)
-   seq_printf(m, " (stolen: %08llx)", obj->stolen->start);
+   seq_printf(m, " (stolen: %08llx)", obj->stolen->base.start);
if (obj->pin_display || obj->fault_mappable) {
char s[3], *t = s;
if (obj->pin_display)
@@ -251,9 +251,9 @@ static int obj_rank_by_stolen(void *priv,
struct drm_i915_gem_object *b =
container_of(B, struct drm_i915_gem_object, obj_exec_link);
 
-   if (a->stolen->start < b->stolen->start)
+   if (a->stolen->base.start < b->stolen->base.start)
return -1;
-   if (a->stolen->start > b->stolen->start)
+   if (a->stolen->base.start > b->stolen->base.start)
return 1;
return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 536d48a..c01e8f7 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -844,6 +844,12 @@ struct i915_ctx_hang_stats {
bool banned;
 };
 
+struct i915_stolen_node {
+   struct drm_mm_node base;
+   struct list_head mm_link;
+   struct drm_i915_gem_object *obj;
+};
+
 /* This must match up with the value previously used for execbuf2.rsvd1. */
 #define DEFAULT_CONTEXT_HANDLE 0
 
@@ -1291,6 +1297,13 @@ struct i915_gem_mm {
 */
struct list_head unbound_list;
 
+   /**
+* List of stolen objects that have been marked as purgeable and
+* thus available for reaping if we need more space for a new
+* allocation. Ordered by time of marking purgeable.
+*/
+   struct list_head stolen_list;
+
/** Usable portion of the GTT for GEM */
unsigned long stolen_base; /* limited to low memory (32-bit) */
 
@@ -2094,7 +2107,7 @@ struct drm_i915_gem_object {
struct list_head vma_list;
 
/** Stolen memory for this object, instead of being backed by shmem. */
-   struct drm_mm_node *stolen;
+   struct i915_stolen_node *stolen;
struct list_head global_list;
 
struct list_head ring_list[I915_NUM_RINGS];
@@ -2102,6 +2115,8 @@ struct drm_i915_gem_object {
struct list_head obj_exec_link;
 
struct list_head batch_pool_link;
+   /** Used to link an object to a list temporarily */
+   struct list_head tmp_link;
 
/**
 * This is set if the object is on the active lists (has pending
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i

[Intel-gfx] [PATCH 07/10] drm/i915: Add support for stealing purgable stolen pages

2016-02-18 Thread ankitprasad . r . sharma
From: Chris Wilson 

If we run out of stolen memory when trying to allocate an object, see if
we can reap enough purgeable objects to free up enough contiguous free
space for the allocation. This is in principle very much like evicting
objects to free up enough contiguous space in the vma when binding
a new object - and you will be forgiven for thinking that the code looks
very similar.

At the moment, we do not allow userspace to allocate objects in stolen,
so there is neither the memory pressure to trigger stolen eviction nor
any purgeable objects inside the stolen arena. However, this will change
in the near future, and so better management and defragmentation of
stolen memory will become a real issue.

v2: Remember to remove the drm_mm_node.

v3: Rebased to the latest drm-intel-nightly (Ankit)

v4: corrected if-else braces format (Tvrtko/kerneldoc)

v5: Rebased to the latest drm-intel-nightly (Ankit)
Added a seperate list to maintain purgable objects from stolen memory
region (Chris/Daniel)

v6: Compiler optimization (merging 2 single loops into one for() loop),
corrected code for object eviction, retire_requests before starting
object eviction (Chris)

v7: Added kernel doc for i915_gem_object_create_stolen()

v8: Check for struct_mutex lock before creating object from stolen
region (Tvrtko)

v9: Renamed variables to make usage clear, added comment, removed onetime
used macro (Tvrtko)

v10: Avoid masking of error when stolen_alloc fails (Tvrtko)

v11: Renamed stolen_link to tmp_link, as it may be used for other
purposes too (Chris)
Used ERR_CAST to cast error pointers while returning

v12: Added lockdep_assert before starting stolen-backed object
eviction (Chris)

Testcase: igt/gem_stolen

Signed-off-by: Chris Wilson 
Signed-off-by: Ankitprasad Sharma 
Reviewed-by: Tvrtko Ursulin 
---
 drivers/gpu/drm/i915/i915_debugfs.c|   6 +-
 drivers/gpu/drm/i915/i915_drv.h|  17 +++-
 drivers/gpu/drm/i915/i915_gem.c|  15 +++
 drivers/gpu/drm/i915/i915_gem_stolen.c | 171 +
 drivers/gpu/drm/i915/intel_pm.c|   4 +-
 5 files changed, 188 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index ec0c2a05e..aa7c7a3 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -174,7 +174,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object 
*obj)
seq_puts(m, ")");
}
if (obj->stolen)
-   seq_printf(m, " (stolen: %08llx)", obj->stolen->start);
+   seq_printf(m, " (stolen: %08llx)", obj->stolen->base.start);
if (obj->pin_display || obj->fault_mappable) {
char s[3], *t = s;
if (obj->pin_display)
@@ -253,9 +253,9 @@ static int obj_rank_by_stolen(void *priv,
struct drm_i915_gem_object *b =
container_of(B, struct drm_i915_gem_object, obj_exec_link);
 
-   if (a->stolen->start < b->stolen->start)
+   if (a->stolen->base.start < b->stolen->base.start)
return -1;
-   if (a->stolen->start > b->stolen->start)
+   if (a->stolen->base.start > b->stolen->base.start)
return 1;
return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 55f2de9..943b301 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -840,6 +840,12 @@ struct i915_ctx_hang_stats {
bool banned;
 };
 
+struct i915_stolen_node {
+   struct drm_mm_node base;
+   struct list_head mm_link;
+   struct drm_i915_gem_object *obj;
+};
+
 /* This must match up with the value previously used for execbuf2.rsvd1. */
 #define DEFAULT_CONTEXT_HANDLE 0
 
@@ -1291,6 +1297,13 @@ struct i915_gem_mm {
 */
struct list_head unbound_list;
 
+   /**
+* List of stolen objects that have been marked as purgeable and
+* thus available for reaping if we need more space for a new
+* allocation. Ordered by time of marking purgeable.
+*/
+   struct list_head stolen_list;
+
/** Usable portion of the GTT for GEM */
unsigned long stolen_base; /* limited to low memory (32-bit) */
 
@@ -2089,7 +2102,7 @@ struct drm_i915_gem_object {
struct list_head vma_list;
 
/** Stolen memory for this object, instead of being backed by shmem. */
-   struct drm_mm_node *stolen;
+   struct i915_stolen_node *stolen;
struct list_head global_list;
 
struct list_head ring_list[I915_NUM_RINGS];
@@ -2097,6 +2110,8 @@ struct drm_i915_gem_object {
struct list_head obj_exec_link;
 
struct list_head batch_pool_link;
+   /** Used to link an object to a list temporarily */
+   struct list_head tmp_link;
 
/**
 * This is set if the object is on the active lists (has pending
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_

[Intel-gfx] [PATCH 07/10] drm/i915: Add support for stealing purgable stolen pages

2016-02-04 Thread ankitprasad . r . sharma
From: Chris Wilson 

If we run out of stolen memory when trying to allocate an object, see if
we can reap enough purgeable objects to free up enough contiguous free
space for the allocation. This is in principle very much like evicting
objects to free up enough contiguous space in the vma when binding
a new object - and you will be forgiven for thinking that the code looks
very similar.

At the moment, we do not allow userspace to allocate objects in stolen,
so there is neither the memory pressure to trigger stolen eviction nor
any purgeable objects inside the stolen arena. However, this will change
in the near future, and so better management and defragmentation of
stolen memory will become a real issue.

v2: Remember to remove the drm_mm_node.

v3: Rebased to the latest drm-intel-nightly (Ankit)

v4: corrected if-else braces format (Tvrtko/kerneldoc)

v5: Rebased to the latest drm-intel-nightly (Ankit)
Added a seperate list to maintain purgable objects from stolen memory
region (Chris/Daniel)

v6: Compiler optimization (merging 2 single loops into one for() loop),
corrected code for object eviction, retire_requests before starting
object eviction (Chris)

v7: Added kernel doc for i915_gem_object_create_stolen()

v8: Check for struct_mutex lock before creating object from stolen
region (Tvrtko)

v9: Renamed variables to make usage clear, added comment, removed onetime
used macro (Tvrtko)

v10: Avoid masking of error when stolen_alloc fails (Tvrtko)

v11: Renamed stolen_link to tmp_link, as it may be used for other
purposes too (Chris)
Used ERR_CAST to cast error pointers while returning

v12: Added lockdep_assert before starting stolen-backed object
eviction (Chris)

Testcase: igt/gem_stolen

Signed-off-by: Chris Wilson 
Signed-off-by: Ankitprasad Sharma 
Reviewed-by: Tvrtko Ursulin 
---
 drivers/gpu/drm/i915/i915_debugfs.c|   6 +-
 drivers/gpu/drm/i915/i915_drv.h|  17 +++-
 drivers/gpu/drm/i915/i915_gem.c|  15 +++
 drivers/gpu/drm/i915/i915_gem_stolen.c | 171 +
 drivers/gpu/drm/i915/intel_pm.c|   4 +-
 5 files changed, 188 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index ec0c2a05e..aa7c7a3 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -174,7 +174,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object 
*obj)
seq_puts(m, ")");
}
if (obj->stolen)
-   seq_printf(m, " (stolen: %08llx)", obj->stolen->start);
+   seq_printf(m, " (stolen: %08llx)", obj->stolen->base.start);
if (obj->pin_display || obj->fault_mappable) {
char s[3], *t = s;
if (obj->pin_display)
@@ -253,9 +253,9 @@ static int obj_rank_by_stolen(void *priv,
struct drm_i915_gem_object *b =
container_of(B, struct drm_i915_gem_object, obj_exec_link);
 
-   if (a->stolen->start < b->stolen->start)
+   if (a->stolen->base.start < b->stolen->base.start)
return -1;
-   if (a->stolen->start > b->stolen->start)
+   if (a->stolen->base.start > b->stolen->base.start)
return 1;
return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 55f2de9..943b301 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -840,6 +840,12 @@ struct i915_ctx_hang_stats {
bool banned;
 };
 
+struct i915_stolen_node {
+   struct drm_mm_node base;
+   struct list_head mm_link;
+   struct drm_i915_gem_object *obj;
+};
+
 /* This must match up with the value previously used for execbuf2.rsvd1. */
 #define DEFAULT_CONTEXT_HANDLE 0
 
@@ -1291,6 +1297,13 @@ struct i915_gem_mm {
 */
struct list_head unbound_list;
 
+   /**
+* List of stolen objects that have been marked as purgeable and
+* thus available for reaping if we need more space for a new
+* allocation. Ordered by time of marking purgeable.
+*/
+   struct list_head stolen_list;
+
/** Usable portion of the GTT for GEM */
unsigned long stolen_base; /* limited to low memory (32-bit) */
 
@@ -2089,7 +2102,7 @@ struct drm_i915_gem_object {
struct list_head vma_list;
 
/** Stolen memory for this object, instead of being backed by shmem. */
-   struct drm_mm_node *stolen;
+   struct i915_stolen_node *stolen;
struct list_head global_list;
 
struct list_head ring_list[I915_NUM_RINGS];
@@ -2097,6 +2110,8 @@ struct drm_i915_gem_object {
struct list_head obj_exec_link;
 
struct list_head batch_pool_link;
+   /** Used to link an object to a list temporarily */
+   struct list_head tmp_link;
 
/**
 * This is set if the object is on the active lists (has pending
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_

[Intel-gfx] [PATCH 07/10] drm/i915: Add support for stealing purgable stolen pages

2016-01-25 Thread ankitprasad . r . sharma
From: Chris Wilson 

If we run out of stolen memory when trying to allocate an object, see if
we can reap enough purgeable objects to free up enough contiguous free
space for the allocation. This is in principle very much like evicting
objects to free up enough contiguous space in the vma when binding
a new object - and you will be forgiven for thinking that the code looks
very similar.

At the moment, we do not allow userspace to allocate objects in stolen,
so there is neither the memory pressure to trigger stolen eviction nor
any purgeable objects inside the stolen arena. However, this will change
in the near future, and so better management and defragmentation of
stolen memory will become a real issue.

v2: Remember to remove the drm_mm_node.

v3: Rebased to the latest drm-intel-nightly (Ankit)

v4: corrected if-else braces format (Tvrtko/kerneldoc)

v5: Rebased to the latest drm-intel-nightly (Ankit)
Added a seperate list to maintain purgable objects from stolen memory
region (Chris/Daniel)

v6: Compiler optimization (merging 2 single loops into one for() loop),
corrected code for object eviction, retire_requests before starting
object eviction (Chris)

v7: Added kernel doc for i915_gem_object_create_stolen()

v8: Check for struct_mutex lock before creating object from stolen
region (Tvrtko)

v9: Renamed variables to make usage clear, added comment, removed onetime
used macro (Tvrtko)

v10: Avoid masking of error when stolen_alloc fails (Tvrtko)

v11: Renamed stolen_link to tmp_link, as it may be used for other
purposes too (Chris)
Used ERR_CAST to cast error pointers while returning

v12: Added lockdep_assert before starting stolen-backed object
eviction (Chris)

Testcase: igt/gem_stolen

Signed-off-by: Chris Wilson 
Signed-off-by: Ankitprasad Sharma 
Reviewed-by: Tvrtko Ursulin 
---
 drivers/gpu/drm/i915/i915_debugfs.c|   6 +-
 drivers/gpu/drm/i915/i915_drv.h|  17 +++-
 drivers/gpu/drm/i915/i915_gem.c|  15 +++
 drivers/gpu/drm/i915/i915_gem_stolen.c | 171 +
 drivers/gpu/drm/i915/intel_pm.c|   4 +-
 5 files changed, 188 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index c5db235..6d5206f 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -174,7 +174,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object 
*obj)
seq_puts(m, ")");
}
if (obj->stolen)
-   seq_printf(m, " (stolen: %08llx)", obj->stolen->start);
+   seq_printf(m, " (stolen: %08llx)", obj->stolen->base.start);
if (obj->pin_display || obj->fault_mappable) {
char s[3], *t = s;
if (obj->pin_display)
@@ -253,9 +253,9 @@ static int obj_rank_by_stolen(void *priv,
struct drm_i915_gem_object *b =
container_of(B, struct drm_i915_gem_object, obj_exec_link);
 
-   if (a->stolen->start < b->stolen->start)
+   if (a->stolen->base.start < b->stolen->base.start)
return -1;
-   if (a->stolen->start > b->stolen->start)
+   if (a->stolen->base.start > b->stolen->base.start)
return 1;
return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0081248..bb9cd9b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -840,6 +840,12 @@ struct i915_ctx_hang_stats {
bool banned;
 };
 
+struct i915_stolen_node {
+   struct drm_mm_node base;
+   struct list_head mm_link;
+   struct drm_i915_gem_object *obj;
+};
+
 /* This must match up with the value previously used for execbuf2.rsvd1. */
 #define DEFAULT_CONTEXT_HANDLE 0
 
@@ -1253,6 +1259,13 @@ struct i915_gem_mm {
 */
struct list_head unbound_list;
 
+   /**
+* List of stolen objects that have been marked as purgeable and
+* thus available for reaping if we need more space for a new
+* allocation. Ordered by time of marking purgeable.
+*/
+   struct list_head stolen_list;
+
/** Usable portion of the GTT for GEM */
unsigned long stolen_base; /* limited to low memory (32-bit) */
 
@@ -2044,7 +2057,7 @@ struct drm_i915_gem_object {
struct list_head vma_list;
 
/** Stolen memory for this object, instead of being backed by shmem. */
-   struct drm_mm_node *stolen;
+   struct i915_stolen_node *stolen;
struct list_head global_list;
 
struct list_head ring_list[I915_NUM_RINGS];
@@ -2052,6 +2065,8 @@ struct drm_i915_gem_object {
struct list_head obj_exec_link;
 
struct list_head batch_pool_link;
+   /** Used to link an object to a list temporarily */
+   struct list_head tmp_link;
 
/**
 * This is set if the object is on the active lists (has pending
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_ge