@@ -3218,6 +3218,7 @@ void i915_gem_reset(struct drm_device *dev)
void
i915_gem_retire_requests_ring(struct intel_engine_cs *ring)
{
+ struct drm_i915_gem_object *obj, *obj_next;
struct drm_i915_gem_request *req, *req_next;
LIST_HEAD(list_head);
unsigned long flags;
@@ -3231,37 +3232,31 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring)
*/
i915_gem_request_notify(ring, false);
+ /*
+ * Note that request entries might be out of order due to rescheduling
+ * and pre-emption. Thus both lists must be processed in their entirety
+ * rather than stopping at the first non-complete entry.
+ */
+
/* Retire requests first as we use it above for the early return.
* If we retire requests last, we may use a later seqno and so clear
* the requests lists without clearing the active list, leading to
* confusion.
*/
- while (!list_empty(&ring->request_list)) {
- struct drm_i915_gem_request *request;
-
- request = list_first_entry(&ring->request_list,
- struct drm_i915_gem_request,
- list);
-
- if (!i915_gem_request_completed(request))
- break;
+ list_for_each_entry_safe(req, req_next, &ring->request_list, list) {
+ if (!i915_gem_request_completed(req))
+ continue;
- i915_gem_request_retire(request);
+ i915_gem_request_retire(req);
}
/* Move any buffers on the active list that are no longer referenced
* by the ringbuffer to the flushing/inactive lists as appropriate,
* before we free the context associated with the requests.
*/
- while (!list_empty(&ring->active_list)) {
- struct drm_i915_gem_object *obj;
-
- obj = list_first_entry(&ring->active_list,
- struct drm_i915_gem_object,
- ring_list[ring->id]);
-
+ list_for_each_entry_safe(obj, obj_next, &ring->active_list, ring_list[ring->id]) {
if (!list_empty(&obj->last_read_req[ring->id]->list))
- break;
+ continue;
i915_gem_object_retire__read(obj, ring->id);
}