summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_guc_submission.c
diff options
context:
space:
mode:
authorOscar Mateo <oscar.mateo@intel.com>2017-03-22 10:39:46 -0700
committerJoonas Lahtinen <joonas.lahtinen@linux.intel.com>2017-03-23 14:57:36 +0200
commit3950bf3dbff1010e3309416f9fe2acbea03156d5 (patch)
tree834203f8504bbb89338c07987f0e479ba9befd64 /drivers/gpu/drm/i915/i915_guc_submission.c
parent73b055349c40ac721f4939263f173c2238524091 (diff)
downloadop-kernel-dev-3950bf3dbff1010e3309416f9fe2acbea03156d5.zip
op-kernel-dev-3950bf3dbff1010e3309416f9fe2acbea03156d5.tar.gz
drm/i915/guc: Add onion teardown to the GuC setup
Starting with intel_guc_loader, down to intel_guc_submission and finally to intel_guc_log. v2: - Null execbuf client outside guc_client_free (Daniele) - Assert if things try to get allocated twice (Daniele/Joonas) - Null guc->log.buf_addr when destroyed (Daniele) - Newline between returning success and error labels (Joonas) - Remove some unnecessary comments (Joonas) - Keep guc_log_create_extras naming convention (Joonas) - Helper function guc_log_has_extras (Joonas) - No need for separate relay_channel create/destroy. It's just another extra. - No need to nullify guc->log.flush_wq when destroyed (Joonas) - Hoist the check for has_extras out of guc_log_create_extras (Joonas) - Try to do i915_guc_log_register/unregister calls (kind of) symmetric (Daniele) - Make sure initel_guc_fini is not called before init is ever called (Daniele) v3: - Remove unnecessary parenthesis (Joonas) - Check for logs enabled on debugfs registration - Rebase on top of Tvrtko's "Fix request re-submission after reset" v4: - Rebased - Comment around enabling/disabling interrupts inside GuC logging (Joonas) Signed-off-by: Oscar Mateo <oscar.mateo@intel.com> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_guc_submission.c')
-rw-r--r--drivers/gpu/drm/i915/i915_guc_submission.c97
1 files changed, 57 insertions, 40 deletions
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 9ba6927..7426eb6 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -911,7 +911,6 @@ err_id:
ida_simple_remove(&guc->ctx_ids, client->ctx_index);
err_client:
kfree(client);
-
return ERR_PTR(ret);
}
@@ -937,7 +936,7 @@ static void guc_policies_init(struct guc_policies *policies)
policies->is_valid = 1;
}
-static void guc_addon_create(struct intel_guc *guc)
+static int guc_addon_create(struct intel_guc *guc)
{
struct drm_i915_private *dev_priv = guc_to_i915(guc);
struct i915_vma *vma;
@@ -953,14 +952,13 @@ static void guc_addon_create(struct intel_guc *guc)
enum intel_engine_id id;
u32 base;
- vma = guc->ads_vma;
- if (!vma) {
- vma = intel_guc_allocate_vma(guc, PAGE_ALIGN(sizeof(*blob)));
- if (IS_ERR(vma))
- return;
+ GEM_BUG_ON(guc->ads_vma);
- guc->ads_vma = vma;
- }
+ vma = intel_guc_allocate_vma(guc, PAGE_ALIGN(sizeof(*blob)));
+ if (IS_ERR(vma))
+ return PTR_ERR(vma);
+
+ guc->ads_vma = vma;
page = i915_vma_first_page(vma);
blob = kmap(page);
@@ -997,6 +995,13 @@ static void guc_addon_create(struct intel_guc *guc)
blob->ads.reg_state_addr = base + ptr_offset(blob, reg_state);
kunmap(page);
+
+ return 0;
+}
+
+static void guc_addon_destroy(struct intel_guc *guc)
+{
+ i915_vma_unpin_and_release(&guc->ads_vma);
}
/*
@@ -1011,6 +1016,7 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
struct intel_guc *guc = &dev_priv->guc;
struct i915_vma *vma;
void *vaddr;
+ int ret;
if (!HAS_GUC_SCHED(dev_priv))
return 0;
@@ -1020,10 +1026,10 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
i915_guc_submission_disable(dev_priv);
if (!i915.enable_guc_submission)
- return 0; /* not enabled */
+ return 0;
if (guc->ctx_pool)
- return 0; /* already allocated */
+ return 0;
vma = intel_guc_allocate_vma(guc, gemsize);
if (IS_ERR(vma))
@@ -1031,15 +1037,23 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
guc->ctx_pool = vma;
- vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB);
- if (IS_ERR(vaddr))
- goto err;
+ vaddr = i915_gem_object_pin_map(guc->ctx_pool->obj, I915_MAP_WB);
+ if (IS_ERR(vaddr)) {
+ ret = PTR_ERR(vaddr);
+ goto err_vma;
+ }
guc->ctx_pool_vaddr = vaddr;
+ ret = intel_guc_log_create(guc);
+ if (ret < 0)
+ goto err_vaddr;
+
+ ret = guc_addon_create(guc);
+ if (ret < 0)
+ goto err_log;
+
ida_init(&guc->ctx_ids);
- intel_guc_log_create(guc);
- guc_addon_create(guc);
guc->execbuf_client = guc_client_alloc(dev_priv,
INTEL_INFO(dev_priv)->ring_mask,
@@ -1047,14 +1061,37 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
dev_priv->kernel_context);
if (IS_ERR(guc->execbuf_client)) {
DRM_ERROR("Failed to create GuC client for execbuf!\n");
- goto err;
+ ret = PTR_ERR(guc->execbuf_client);
+ goto err_ads;
}
return 0;
-err:
- i915_guc_submission_fini(dev_priv);
- return -ENOMEM;
+err_ads:
+ guc_addon_destroy(guc);
+err_log:
+ intel_guc_log_destroy(guc);
+err_vaddr:
+ i915_gem_object_unpin_map(guc->ctx_pool->obj);
+err_vma:
+ i915_vma_unpin_and_release(&guc->ctx_pool);
+ return ret;
+}
+
+void i915_guc_submission_fini(struct drm_i915_private *dev_priv)
+{
+ struct intel_guc *guc = &dev_priv->guc;
+
+ if (!i915.enable_guc_submission)
+ return 0;
+
+ guc_client_free(guc->execbuf_client);
+ guc->execbuf_client = NULL;
+ ida_destroy(&guc->ctx_ids);
+ guc_addon_destroy(guc);
+ intel_guc_log_destroy(guc);
+ i915_gem_object_unpin_map(guc->ctx_pool->obj);
+ i915_vma_unpin_and_release(&guc->ctx_pool);
}
static void guc_reset_wq(struct i915_guc_client *client)
@@ -1199,26 +1236,6 @@ void i915_guc_submission_disable(struct drm_i915_private *dev_priv)
intel_engines_reset_default_submission(dev_priv);
}
-void i915_guc_submission_fini(struct drm_i915_private *dev_priv)
-{
- struct intel_guc *guc = &dev_priv->guc;
- struct i915_guc_client *client;
-
- client = fetch_and_zero(&guc->execbuf_client);
- if (client && !IS_ERR(client))
- guc_client_free(client);
-
- i915_vma_unpin_and_release(&guc->ads_vma);
- i915_vma_unpin_and_release(&guc->log.vma);
-
- if (guc->ctx_pool_vaddr) {
- ida_destroy(&guc->ctx_ids);
- i915_gem_object_unpin_map(guc->ctx_pool->obj);
- }
-
- i915_vma_unpin_and_release(&guc->ctx_pool);
-}
-
/**
* intel_guc_suspend() - notify GuC entering suspend state
* @dev_priv: i915 device private
OpenPOWER on IntegriCloud