drm/i915: Do not leak dev_priv->l3_parity.remap_info[]
authorJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Fri, 28 Apr 2017 07:58:39 +0000 (10:58 +0300)
committerJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Tue, 2 May 2017 09:09:13 +0000 (12:09 +0300)
Add intel_irq_fini() for placing the deinitialization code,
starting with freeing dev_priv->l3_parity.remap_info[].

Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1493366319-18515-1-git-send-email-joonas.lahtinen@linux.intel.com
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_sysfs.c

index 2d3c426465d3fc50048a306b35197c14b79b42e5..452c26505018ac1839a871e15280e8998d49eaad 100644 (file)
@@ -852,7 +852,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
        intel_init_audio_hooks(dev_priv);
        ret = i915_gem_load_init(dev_priv);
        if (ret < 0)
-               goto err_workqueues;
+               goto err_irq;
 
        intel_display_crc_init(dev_priv);
 
@@ -864,7 +864,8 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
 
        return 0;
 
-err_workqueues:
+err_irq:
+       intel_irq_fini(dev_priv);
        i915_workqueues_cleanup(dev_priv);
 err_engines:
        i915_engines_cleanup(dev_priv);
@@ -879,6 +880,7 @@ static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
 {
        i915_perf_fini(dev_priv);
        i915_gem_load_cleanup(dev_priv);
+       intel_irq_fini(dev_priv);
        i915_workqueues_cleanup(dev_priv);
        i915_engines_cleanup(dev_priv);
 }
index 720fa3ecd664d782f6b4d5da239c1fb155456d90..4588b3efe7303a77b3ea89e791b5c364bb443242 100644 (file)
@@ -3057,6 +3057,7 @@ void i915_handle_error(struct drm_i915_private *dev_priv,
                       const char *fmt, ...);
 
 extern void intel_irq_init(struct drm_i915_private *dev_priv);
+extern void intel_irq_fini(struct drm_i915_private *dev_priv);
 int intel_irq_install(struct drm_i915_private *dev_priv);
 void intel_irq_uninstall(struct drm_i915_private *dev_priv);
 
index fd97fe00cd0d2ad00e1c7258eeb51ecf0f60d4c1..0e4dcbeb4d06a9e304b1f68bfc772414ff61cea9 100644 (file)
@@ -1236,7 +1236,7 @@ out:
 static void ivybridge_parity_work(struct work_struct *work)
 {
        struct drm_i915_private *dev_priv =
-               container_of(work, struct drm_i915_private, l3_parity.error_work);
+               container_of(work, typeof(*dev_priv), l3_parity.error_work);
        u32 error_status, row, bank, subbank;
        char *parity_event[6];
        uint32_t misccpctl;
@@ -4233,11 +4233,15 @@ static void i965_irq_uninstall(struct drm_device * dev)
 void intel_irq_init(struct drm_i915_private *dev_priv)
 {
        struct drm_device *dev = &dev_priv->drm;
+       int i;
 
        intel_hpd_init_work(dev_priv);
 
        INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);
+
        INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
+       for (i = 0; i < MAX_L3_SLICES; ++i)
+               dev_priv->l3_parity.remap_info[i] = NULL;
 
        if (HAS_GUC_SCHED(dev_priv))
                dev_priv->pm_guc_events = GEN9_GUC_TO_HOST_INT_EVENT;
@@ -4362,6 +4366,20 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
        }
 }
 
+/**
+ * intel_irq_fini - deinitializes IRQ support
+ * @i915: i915 device instance
+ *
+ * This function deinitializes all the IRQ support.
+ */
+void intel_irq_fini(struct drm_i915_private *i915)
+{
+       int i;
+
+       for (i = 0; i < MAX_L3_SLICES; ++i)
+               kfree(i915->l3_parity.remap_info[i]);
+}
+
 /**
  * intel_irq_install - enables the hardware interrupt
  * @dev_priv: i915 device instance
index a6ad1c279dc1ec97a5ce3111b3362a840104ae53..1eef3fae4db31312f788372d72470ad2e9b38f5c 100644 (file)
@@ -181,8 +181,8 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
        struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
        struct drm_device *dev = &dev_priv->drm;
        struct i915_gem_context *ctx;
-       u32 *temp = NULL; /* Just here to make handling failures easy */
        int slice = (int)(uintptr_t)attr->private;
+       u32 **remap_info;
        int ret;
 
        ret = l3_access_valid(dev_priv, offset);
@@ -193,11 +193,12 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
        if (ret)
                return ret;
 
-       if (!dev_priv->l3_parity.remap_info[slice]) {
-               temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL);
-               if (!temp) {
-                       mutex_unlock(&dev->struct_mutex);
-                       return -ENOMEM;
+       remap_info = &dev_priv->l3_parity.remap_info[slice];
+       if (!*remap_info) {
+               *remap_info = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL);
+               if (!*remap_info) {
+                       ret = -ENOMEM;
+                       goto out;
                }
        }
 
@@ -205,18 +206,18 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
         * aren't propagated. Since I cannot find a stable way to reset the GPU
         * at this point it is left as a TODO.
        */
-       if (temp)
-               dev_priv->l3_parity.remap_info[slice] = temp;
-
-       memcpy(dev_priv->l3_parity.remap_info[slice] + (offset/4), buf, count);
+       memcpy(*remap_info + (offset/4), buf, count);
 
        /* NB: We defer the remapping until we switch to the context */
        list_for_each_entry(ctx, &dev_priv->context_list, link)
                ctx->remap_slice |= (1<<slice);
 
+       ret = count;
+
+out:
        mutex_unlock(&dev->struct_mutex);
 
-       return count;
+       return ret;
 }
 
 static struct bin_attribute dpf_attrs = {