@@ -1940,23 +1940,34 @@ int i915_reset_engine(struct intel_engine_cs *engine)
*/
i915_gem_reset_engine(engine);
- /* forcing engine to idle */
- ret = intel_request_reset_engine(engine);
- if (ret) {
- DRM_ERROR("Failed to disable %s\n", engine->name);
- goto error;
- }
+ if (!dev_priv->guc.execbuf_client) {
+ /* forcing engine to idle */
+ ret = intel_request_reset_engine(engine);
+ if (ret) {
+ DRM_ERROR("Failed to disable %s\n", engine->name);
+ goto error;
+ }
- /* finally, reset engine */
- ret = intel_gpu_reset(dev_priv, intel_engine_flag(engine));
- if (ret) {
- DRM_ERROR("Failed to reset %s, ret=%d\n", engine->name, ret);
+ /* finally, reset engine */
+ ret = intel_gpu_reset(dev_priv, intel_engine_flag(engine));
+ if (ret) {
+ DRM_ERROR("Failed to reset %s, ret=%d\n",
+ engine->name, ret);
+ intel_unrequest_reset_engine(engine);
+ goto error;
+ }
+
+ /* be sure the request reset bit gets cleared */
intel_unrequest_reset_engine(engine);
- goto error;
- }
- /* be sure the request reset bit gets cleared */
- intel_unrequest_reset_engine(engine);
+ } else {
+ ret = i915_guc_request_engine_reset(engine);
+ if (ret) {
+ DRM_ERROR("GuC failed to reset %s, ret=%d\n",
+ engine->name, ret);
+ goto error;
+ }
+ }
/* i915_gem_reset_prepare revoked the fences */
i915_gem_restore_fences(dev_priv);
@@ -1967,6 +1978,10 @@ int i915_reset_engine(struct intel_engine_cs *engine)
if (ret)
goto error;
+ /* for guc too */
+ if (dev_priv->guc.execbuf_client)
+ i915_guc_submission_reenable_engine(engine);
+
error->reset_engine_count[engine->id]++;
wakeup:
@@ -3048,6 +3048,7 @@ extern void i915_reset(struct drm_i915_private *dev_priv, u32 engine_mask);
extern bool intel_has_reset_engine(struct drm_i915_private *dev_priv);
extern int intel_request_reset_engine(struct intel_engine_cs *engine);
extern void intel_unrequest_reset_engine(struct intel_engine_cs *engine);
+extern int i915_guc_request_engine_reset(struct intel_engine_cs *engine);
extern int intel_guc_reset(struct drm_i915_private *dev_priv);
extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine);
extern void intel_hangcheck_init(struct drm_i915_private *dev_priv);
@@ -1335,6 +1335,25 @@ void i915_guc_submission_disable(struct drm_i915_private *dev_priv)
guc->execbuf_client = NULL;
}
+void i915_guc_submission_reenable_engine(struct intel_engine_cs *engine)
+{
+ struct drm_i915_private *dev_priv = engine->i915;
+ struct intel_guc *guc = &dev_priv->guc;
+ struct i915_guc_client *client = guc->execbuf_client;
+ const int wqi_size = sizeof(struct guc_wq_item);
+ struct drm_i915_gem_request *rq;
+
+ GEM_BUG_ON(!client);
+ intel_guc_sample_forcewake(guc);
+
+ spin_lock_irq(&engine->timeline->lock);
+ list_for_each_entry(rq, &engine->timeline->requests, link) {
+ guc_client_update_wq_rsvd(client, wqi_size);
+ __i915_guc_submit(rq);
+ }
+ spin_unlock_irq(&engine->timeline->lock);
+}
+
/**
* intel_guc_suspend() - notify GuC entering suspend state
* @dev_priv: i915 device private
@@ -1386,3 +1405,32 @@ int intel_guc_resume(struct drm_i915_private *dev_priv)
return intel_guc_send(guc, data, ARRAY_SIZE(data));
}
+
+int i915_guc_request_engine_reset(struct intel_engine_cs *engine)
+{
+ struct drm_i915_private *dev_priv = engine->i915;
+ struct intel_guc *guc = &dev_priv->guc;
+ struct i915_gem_context *ctx;
+ u32 data[7];
+
+ if (!i915.enable_guc_submission)
+ return 0;
+
+ ctx = dev_priv->kernel_context;
+
+ /*
+ * The affected context report is populated by GuC and is provided
+ * to the driver using the shared page. We request for it but don't
+ * use it as scheduler has all of these details.
+ */
+ data[0] = INTEL_GUC_ACTION_REQUEST_ENGINE_RESET;
+ data[1] = engine->guc_id;
+ data[2] = INTEL_GUC_RESET_OPTION_REPORT_AFFECTED_CONTEXTS;
+ data[3] = 0;
+ data[4] = 0;
+ data[5] = guc->execbuf_client->stage_id;
+ /* first page is shared data with GuC */
+ data[6] = guc_ggtt_offset(ctx->engine[RCS].state);
+
+ return intel_guc_send(guc, data, ARRAY_SIZE(data));
+}
@@ -506,6 +506,7 @@ union guc_log_control {
/* This Action will be programmed in C180 - SOFT_SCRATCH_O_REG */
enum intel_guc_action {
INTEL_GUC_ACTION_DEFAULT = 0x0,
+ INTEL_GUC_ACTION_REQUEST_ENGINE_RESET = 0x3,
INTEL_GUC_ACTION_SAMPLE_FORCEWAKE = 0x6,
INTEL_GUC_ACTION_ALLOCATE_DOORBELL = 0x10,
INTEL_GUC_ACTION_DEALLOCATE_DOORBELL = 0x20,
@@ -519,6 +520,11 @@ enum intel_guc_action {
INTEL_GUC_ACTION_LIMIT
};
+/* Reset engine options */
+enum action_engine_reset_options {
+ INTEL_GUC_RESET_OPTION_REPORT_AFFECTED_CONTEXTS = 0x10,
+};
+
/*
* The GuC sends its response to a command by overwriting the
* command in SS0. The response is distinguishable from a command
@@ -1187,14 +1187,15 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine)
/* After a GPU reset, we may have requests to replay */
clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted);
- if (!i915.enable_guc_submission && !execlists_elsp_idle(engine)) {
+ if (!execlists_elsp_idle(engine)) {
DRM_DEBUG_DRIVER("Restarting %s from requests [0x%x, 0x%x]\n",
engine->name,
port_seqno(&engine->execlist_port[0]),
port_seqno(&engine->execlist_port[1]));
engine->execlist_port[0].count = 0;
engine->execlist_port[1].count = 0;
- execlists_submit_ports(engine);
+ if (!dev_priv->guc.execbuf_client)
+ execlists_submit_ports(engine);
}
return 0;
@@ -221,6 +221,7 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *rq);
void i915_guc_wq_unreserve(struct drm_i915_gem_request *request);
void i915_guc_submission_disable(struct drm_i915_private *dev_priv);
void i915_guc_submission_fini(struct drm_i915_private *dev_priv);
+void i915_guc_submission_reenable_engine(struct intel_engine_cs *engine);
struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size);
/* intel_guc_log.c */
@@ -1756,14 +1756,9 @@ bool intel_has_gpu_reset(struct drm_i915_private *dev_priv)
return intel_get_gpu_reset(dev_priv) != NULL;
}
-/*
- * When GuC submission is enabled, GuC manages ELSP and can initiate the
- * engine reset too. For now, fall back to full GPU reset if it is enabled.
- */
bool intel_has_reset_engine(struct drm_i915_private *dev_priv)
{
return (dev_priv->info.has_reset_engine &&
- !dev_priv->guc.execbuf_client &&
i915.reset == 2);
}