Commit a9d8adad authored by Alex Dai's avatar Alex Dai Committed by Tvrtko Ursulin

drm/i915/guc: Fix a memory leak where guc->execbuf_client is not freed

During driver unloading, the guc_client created for command submission
needs to be released to avoid memory leak.

The struct_mutex needs to be held before tearing down GuC.

v1: Move i915_guc_submission_disable out of i915_guc_submission_fini and
    take struct_mutex lock before release GuC client. (Dave Gordon)
v2: Add the locking for failure case in guc_fw_fetch. (Dave Gordon)
    Add i915_guc_submission_fini for failure case in intel_guc_ucode_load.
Signed-off-by: default avatarAlex Dai <yu.dai@intel.com>
Reviewed-by: default avatarDave Gordon <david.s.gordon@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1452711710-4505-1-git-send-email-yu.dai@intel.com
parent 82352e90
...@@ -445,6 +445,7 @@ int intel_guc_ucode_load(struct drm_device *dev) ...@@ -445,6 +445,7 @@ int intel_guc_ucode_load(struct drm_device *dev)
direct_interrupts_to_host(dev_priv); direct_interrupts_to_host(dev_priv);
i915_guc_submission_disable(dev); i915_guc_submission_disable(dev);
i915_guc_submission_fini(dev);
return err; return err;
} }
...@@ -561,10 +562,12 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) ...@@ -561,10 +562,12 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
DRM_ERROR("Failed to fetch GuC firmware from %s (error %d)\n", DRM_ERROR("Failed to fetch GuC firmware from %s (error %d)\n",
guc_fw->guc_fw_path, err); guc_fw->guc_fw_path, err);
mutex_lock(&dev->struct_mutex);
obj = guc_fw->guc_fw_obj; obj = guc_fw->guc_fw_obj;
if (obj) if (obj)
drm_gem_object_unreference(&obj->base); drm_gem_object_unreference(&obj->base);
guc_fw->guc_fw_obj = NULL; guc_fw->guc_fw_obj = NULL;
mutex_unlock(&dev->struct_mutex);
release_firmware(fw); /* OK even if fw is NULL */ release_firmware(fw); /* OK even if fw is NULL */
guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_FAIL; guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_FAIL;
...@@ -631,10 +634,11 @@ void intel_guc_ucode_fini(struct drm_device *dev) ...@@ -631,10 +634,11 @@ void intel_guc_ucode_fini(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
mutex_lock(&dev->struct_mutex);
direct_interrupts_to_host(dev_priv); direct_interrupts_to_host(dev_priv);
i915_guc_submission_disable(dev);
i915_guc_submission_fini(dev); i915_guc_submission_fini(dev);
mutex_lock(&dev->struct_mutex);
if (guc_fw->guc_fw_obj) if (guc_fw->guc_fw_obj)
drm_gem_object_unreference(&guc_fw->guc_fw_obj->base); drm_gem_object_unreference(&guc_fw->guc_fw_obj->base);
guc_fw->guc_fw_obj = NULL; guc_fw->guc_fw_obj = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment