Commit 3f0acf25 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-fixes-2022-06-16' of...

Merge tag 'drm-intel-fixes-2022-06-16' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes

drm/i915 fixes for v5.19-rc3:
- Fix page fault on error state read
- Fix memory leaks in per-gt sysfs
- Fix multiple fence handling
- Remove accidental static from a local variable
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/8735g5xd25.fsf@intel.com
parents 2f90ec12 2636e008
...@@ -999,7 +999,8 @@ static int eb_validate_vmas(struct i915_execbuffer *eb) ...@@ -999,7 +999,8 @@ static int eb_validate_vmas(struct i915_execbuffer *eb)
} }
} }
err = dma_resv_reserve_fences(vma->obj->base.resv, 1); /* Reserve enough slots to accommodate composite fences */
err = dma_resv_reserve_fences(vma->obj->base.resv, eb->num_batches);
if (err) if (err)
return err; return err;
......
...@@ -785,6 +785,7 @@ void intel_gt_driver_unregister(struct intel_gt *gt) ...@@ -785,6 +785,7 @@ void intel_gt_driver_unregister(struct intel_gt *gt)
{ {
intel_wakeref_t wakeref; intel_wakeref_t wakeref;
intel_gt_sysfs_unregister(gt);
intel_rps_driver_unregister(&gt->rps); intel_rps_driver_unregister(&gt->rps);
intel_gsc_fini(&gt->gsc); intel_gsc_fini(&gt->gsc);
......
...@@ -24,7 +24,7 @@ bool is_object_gt(struct kobject *kobj) ...@@ -24,7 +24,7 @@ bool is_object_gt(struct kobject *kobj)
static struct intel_gt *kobj_to_gt(struct kobject *kobj) static struct intel_gt *kobj_to_gt(struct kobject *kobj)
{ {
return container_of(kobj, struct kobj_gt, base)->gt; return container_of(kobj, struct intel_gt, sysfs_gt);
} }
struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev, struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
...@@ -72,9 +72,9 @@ static struct attribute *id_attrs[] = { ...@@ -72,9 +72,9 @@ static struct attribute *id_attrs[] = {
}; };
ATTRIBUTE_GROUPS(id); ATTRIBUTE_GROUPS(id);
/* A kobject needs a release() method even if it does nothing */
static void kobj_gt_release(struct kobject *kobj) static void kobj_gt_release(struct kobject *kobj)
{ {
kfree(kobj);
} }
static struct kobj_type kobj_gt_type = { static struct kobj_type kobj_gt_type = {
...@@ -85,8 +85,6 @@ static struct kobj_type kobj_gt_type = { ...@@ -85,8 +85,6 @@ static struct kobj_type kobj_gt_type = {
void intel_gt_sysfs_register(struct intel_gt *gt) void intel_gt_sysfs_register(struct intel_gt *gt)
{ {
struct kobj_gt *kg;
/* /*
* We need to make things right with the * We need to make things right with the
* ABI compatibility. The files were originally * ABI compatibility. The files were originally
...@@ -98,25 +96,22 @@ void intel_gt_sysfs_register(struct intel_gt *gt) ...@@ -98,25 +96,22 @@ void intel_gt_sysfs_register(struct intel_gt *gt)
if (gt_is_root(gt)) if (gt_is_root(gt))
intel_gt_sysfs_pm_init(gt, gt_get_parent_obj(gt)); intel_gt_sysfs_pm_init(gt, gt_get_parent_obj(gt));
kg = kzalloc(sizeof(*kg), GFP_KERNEL); /* init and xfer ownership to sysfs tree */
if (!kg) if (kobject_init_and_add(&gt->sysfs_gt, &kobj_gt_type,
gt->i915->sysfs_gt, "gt%d", gt->info.id))
goto exit_fail; goto exit_fail;
kobject_init(&kg->base, &kobj_gt_type); intel_gt_sysfs_pm_init(gt, &gt->sysfs_gt);
kg->gt = gt;
/* xfer ownership to sysfs tree */
if (kobject_add(&kg->base, gt->i915->sysfs_gt, "gt%d", gt->info.id))
goto exit_kobj_put;
intel_gt_sysfs_pm_init(gt, &kg->base);
return; return;
exit_kobj_put:
kobject_put(&kg->base);
exit_fail: exit_fail:
kobject_put(&gt->sysfs_gt);
drm_warn(&gt->i915->drm, drm_warn(&gt->i915->drm,
"failed to initialize gt%d sysfs root\n", gt->info.id); "failed to initialize gt%d sysfs root\n", gt->info.id);
} }
void intel_gt_sysfs_unregister(struct intel_gt *gt)
{
kobject_put(&gt->sysfs_gt);
}
...@@ -13,11 +13,6 @@ ...@@ -13,11 +13,6 @@
struct intel_gt; struct intel_gt;
struct kobj_gt {
struct kobject base;
struct intel_gt *gt;
};
bool is_object_gt(struct kobject *kobj); bool is_object_gt(struct kobject *kobj);
struct drm_i915_private *kobj_to_i915(struct kobject *kobj); struct drm_i915_private *kobj_to_i915(struct kobject *kobj);
...@@ -28,6 +23,7 @@ intel_gt_create_kobj(struct intel_gt *gt, ...@@ -28,6 +23,7 @@ intel_gt_create_kobj(struct intel_gt *gt,
const char *name); const char *name);
void intel_gt_sysfs_register(struct intel_gt *gt); void intel_gt_sysfs_register(struct intel_gt *gt);
void intel_gt_sysfs_unregister(struct intel_gt *gt);
struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev, struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
const char *name); const char *name);
......
...@@ -224,6 +224,9 @@ struct intel_gt { ...@@ -224,6 +224,9 @@ struct intel_gt {
} mocs; } mocs;
struct intel_pxp pxp; struct intel_pxp pxp;
/* gt/gtN sysfs */
struct kobject sysfs_gt;
}; };
enum intel_gt_scratch_field { enum intel_gt_scratch_field {
......
...@@ -156,7 +156,7 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) ...@@ -156,7 +156,7 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
[INTEL_UC_FW_TYPE_GUC] = { blobs_guc, ARRAY_SIZE(blobs_guc) }, [INTEL_UC_FW_TYPE_GUC] = { blobs_guc, ARRAY_SIZE(blobs_guc) },
[INTEL_UC_FW_TYPE_HUC] = { blobs_huc, ARRAY_SIZE(blobs_huc) }, [INTEL_UC_FW_TYPE_HUC] = { blobs_huc, ARRAY_SIZE(blobs_huc) },
}; };
static const struct uc_fw_platform_requirement *fw_blobs; const struct uc_fw_platform_requirement *fw_blobs;
enum intel_platform p = INTEL_INFO(i915)->platform; enum intel_platform p = INTEL_INFO(i915)->platform;
u32 fw_count; u32 fw_count;
u8 rev = INTEL_REVID(i915); u8 rev = INTEL_REVID(i915);
......
...@@ -166,7 +166,14 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj, ...@@ -166,7 +166,14 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
struct device *kdev = kobj_to_dev(kobj); struct device *kdev = kobj_to_dev(kobj);
struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
struct i915_gpu_coredump *gpu; struct i915_gpu_coredump *gpu;
ssize_t ret; ssize_t ret = 0;
/*
* FIXME: Concurrent clients triggering resets and reading + clearing
* dumps can cause inconsistent sysfs reads when a user calls in with a
* non-zero offset to complete a prior partial read but the
* gpu_coredump has been cleared or replaced.
*/
gpu = i915_first_error_state(i915); gpu = i915_first_error_state(i915);
if (IS_ERR(gpu)) { if (IS_ERR(gpu)) {
...@@ -178,8 +185,10 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj, ...@@ -178,8 +185,10 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
const char *str = "No error state collected\n"; const char *str = "No error state collected\n";
size_t len = strlen(str); size_t len = strlen(str);
ret = min_t(size_t, count, len - off); if (off < len) {
memcpy(buf, str + off, ret); ret = min_t(size_t, count, len - off);
memcpy(buf, str + off, ret);
}
} }
return ret; return ret;
...@@ -259,4 +268,6 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv) ...@@ -259,4 +268,6 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv)
device_remove_bin_file(kdev, &dpf_attrs_1); device_remove_bin_file(kdev, &dpf_attrs_1);
device_remove_bin_file(kdev, &dpf_attrs); device_remove_bin_file(kdev, &dpf_attrs);
kobject_put(dev_priv->sysfs_gt);
} }
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
*/ */
#include <linux/sched/mm.h> #include <linux/sched/mm.h>
#include <linux/dma-fence-array.h>
#include <drm/drm_gem.h> #include <drm/drm_gem.h>
#include "display/intel_frontbuffer.h" #include "display/intel_frontbuffer.h"
...@@ -1823,6 +1824,21 @@ int _i915_vma_move_to_active(struct i915_vma *vma, ...@@ -1823,6 +1824,21 @@ int _i915_vma_move_to_active(struct i915_vma *vma,
if (unlikely(err)) if (unlikely(err))
return err; return err;
/*
* Reserve fences slot early to prevent an allocation after preparing
* the workload and associating fences with dma_resv.
*/
if (fence && !(flags & __EXEC_OBJECT_NO_RESERVE)) {
struct dma_fence *curr;
int idx;
dma_fence_array_for_each(curr, idx, fence)
;
err = dma_resv_reserve_fences(vma->obj->base.resv, idx);
if (unlikely(err))
return err;
}
if (flags & EXEC_OBJECT_WRITE) { if (flags & EXEC_OBJECT_WRITE) {
struct intel_frontbuffer *front; struct intel_frontbuffer *front;
...@@ -1832,31 +1848,23 @@ int _i915_vma_move_to_active(struct i915_vma *vma, ...@@ -1832,31 +1848,23 @@ int _i915_vma_move_to_active(struct i915_vma *vma,
i915_active_add_request(&front->write, rq); i915_active_add_request(&front->write, rq);
intel_frontbuffer_put(front); intel_frontbuffer_put(front);
} }
}
if (!(flags & __EXEC_OBJECT_NO_RESERVE)) { if (fence) {
err = dma_resv_reserve_fences(vma->obj->base.resv, 1); struct dma_fence *curr;
if (unlikely(err)) enum dma_resv_usage usage;
return err; int idx;
}
if (fence) { obj->read_domains = 0;
dma_resv_add_fence(vma->obj->base.resv, fence, if (flags & EXEC_OBJECT_WRITE) {
DMA_RESV_USAGE_WRITE); usage = DMA_RESV_USAGE_WRITE;
obj->write_domain = I915_GEM_DOMAIN_RENDER; obj->write_domain = I915_GEM_DOMAIN_RENDER;
obj->read_domains = 0; } else {
} usage = DMA_RESV_USAGE_READ;
} else {
if (!(flags & __EXEC_OBJECT_NO_RESERVE)) {
err = dma_resv_reserve_fences(vma->obj->base.resv, 1);
if (unlikely(err))
return err;
} }
if (fence) { dma_fence_array_for_each(curr, idx, fence)
dma_resv_add_fence(vma->obj->base.resv, fence, dma_resv_add_fence(vma->obj->base.resv, curr, usage);
DMA_RESV_USAGE_READ);
obj->write_domain = 0;
}
} }
if (flags & EXEC_OBJECT_NEEDS_FENCE && vma->fence) if (flags & EXEC_OBJECT_NEEDS_FENCE && vma->fence)
......
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