]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
accel/ivpu: Fix PM related deadlocks in MS IOCTLs
authorJacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Tue, 25 Mar 2025 11:43:06 +0000 (12:43 +0100)
committerJacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Mon, 31 Mar 2025 12:19:05 +0000 (14:19 +0200)
Prevent runtime resume/suspend while MS IOCTLs are in progress.
Failed suspend will call ivpu_ms_cleanup() that would try to acquire
file_priv->ms_lock, which is already held by the IOCTLs.

Fixes: cdfad4db7756 ("accel/ivpu: Add NPU profiling support")
Cc: stable@vger.kernel.org # v6.11+
Signed-off-by: Maciej Falkowski <maciej.falkowski@linux.intel.com>
Reviewed-by: Lizhi Hou <lizhi.hou@amd.com>
Signed-off-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Link: https://lore.kernel.org/r/20250325114306.3740022-3-maciej.falkowski@linux.intel.com
drivers/accel/ivpu/ivpu_debugfs.c
drivers/accel/ivpu/ivpu_ms.c

index 8180b95ed69dc79c1af4971e4f13b249bcb8fa30..093a2e93b0b39472e26d0f68a1283f82a5c82f3f 100644 (file)
@@ -331,7 +331,7 @@ ivpu_force_recovery_fn(struct file *file, const char __user *user_buf, size_t si
                return -EINVAL;
 
        ret = ivpu_rpm_get(vdev);
-       if (ret)
+       if (ret < 0)
                return ret;
 
        ivpu_pm_trigger_recovery(vdev, "debugfs");
@@ -382,7 +382,7 @@ static int dct_active_set(void *data, u64 active_percent)
                return -EINVAL;
 
        ret = ivpu_rpm_get(vdev);
-       if (ret)
+       if (ret < 0)
                return ret;
 
        if (active_percent)
index eb485cf15ad64f85c02efaa7e3029d928f94134c..2a043baf10ca17ca190ac765cc4ca526a89ae130 100644 (file)
@@ -45,6 +45,10 @@ int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
            args->sampling_period_ns < MS_MIN_SAMPLE_PERIOD_NS)
                return -EINVAL;
 
+       ret = ivpu_rpm_get(vdev);
+       if (ret < 0)
+               return ret;
+
        mutex_lock(&file_priv->ms_lock);
 
        if (get_instance_by_mask(file_priv, args->metric_group_mask)) {
@@ -97,6 +101,8 @@ err_free_ms:
        kfree(ms);
 unlock:
        mutex_unlock(&file_priv->ms_lock);
+
+       ivpu_rpm_put(vdev);
        return ret;
 }
 
@@ -161,6 +167,10 @@ int ivpu_ms_get_data_ioctl(struct drm_device *dev, void *data, struct drm_file *
        if (!args->metric_group_mask)
                return -EINVAL;
 
+       ret = ivpu_rpm_get(vdev);
+       if (ret < 0)
+               return ret;
+
        mutex_lock(&file_priv->ms_lock);
 
        ms = get_instance_by_mask(file_priv, args->metric_group_mask);
@@ -188,6 +198,7 @@ int ivpu_ms_get_data_ioctl(struct drm_device *dev, void *data, struct drm_file *
 unlock:
        mutex_unlock(&file_priv->ms_lock);
 
+       ivpu_rpm_put(vdev);
        return ret;
 }
 
@@ -205,11 +216,17 @@ int ivpu_ms_stop_ioctl(struct drm_device *dev, void *data, struct drm_file *file
 {
        struct ivpu_file_priv *file_priv = file->driver_priv;
        struct drm_ivpu_metric_streamer_stop *args = data;
+       struct ivpu_device *vdev = file_priv->vdev;
        struct ivpu_ms_instance *ms;
+       int ret;
 
        if (!args->metric_group_mask)
                return -EINVAL;
 
+       ret = ivpu_rpm_get(vdev);
+       if (ret < 0)
+               return ret;
+
        mutex_lock(&file_priv->ms_lock);
 
        ms = get_instance_by_mask(file_priv, args->metric_group_mask);
@@ -218,6 +235,7 @@ int ivpu_ms_stop_ioctl(struct drm_device *dev, void *data, struct drm_file *file
 
        mutex_unlock(&file_priv->ms_lock);
 
+       ivpu_rpm_put(vdev);
        return ms ? 0 : -EINVAL;
 }