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
Unified · Split
| @@ -999,7 +999,8 @@ static int eb_validate_vmas(struct i915_execbuffer *eb) · 998 unmodified lines | ||
| 999 | 999 | } |
| 1000 | 1000 | } |
| 1001 | 1001 | |
| 1002 | − err = dma_resv_reserve_fences(vma->obj->base.resv, 1); | |
| 1002 | + /* Reserve enough slots to accommodate composite fences */ | |
| 1003 | + err = dma_resv_reserve_fences(vma->obj->base.resv, eb->num_batches); | |
| 1003 | 1004 | if (err) |
| 1004 | 1005 | return err; |
| 1005 | 1006 | |
| @@ -785,6 +785,7 @@ void intel_gt_driver_unregister(struct intel_gt *gt) · 784 unmodified lines | ||
| 785 | 785 | { |
| 786 | 786 | intel_wakeref_t wakeref; |
| 787 | 787 | |
| 788 | + intel_gt_sysfs_unregister(gt); | |
| 788 | 789 | intel_rps_driver_unregister(>->rps); |
| 789 | 790 | intel_gsc_fini(>->gsc); |
| 790 | 791 | |
| @@ -24,7 +24,7 @@ bool is_object_gt(struct kobject *kobj) · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | static struct intel_gt *kobj_to_gt(struct kobject *kobj) |
| 26 | 26 | { |
| 27 | − return container_of(kobj, struct kobj_gt, base)->gt; | |
| 27 | + return container_of(kobj, struct intel_gt, sysfs_gt); | |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | 30 | struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev, |
| @@ -72,9 +72,9 @@ static struct attribute *id_attrs[] = { · 41 unmodified lines | ||
| 72 | 72 | }; |
| 73 | 73 | ATTRIBUTE_GROUPS(id); |
| 74 | 74 | |
| 75 | +/* A kobject needs a release() method even if it does nothing */ | |
| 75 | 76 | static void kobj_gt_release(struct kobject *kobj) |
| 76 | 77 | { |
| 77 | − kfree(kobj); | |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | 80 | static struct kobj_type kobj_gt_type = { |
| @@ -85,8 +85,6 @@ static struct kobj_type kobj_gt_type = { · 4 unmodified lines | ||
| 85 | 85 | |
| 86 | 86 | void intel_gt_sysfs_register(struct intel_gt *gt) |
| 87 | 87 | { |
| 88 | − struct kobj_gt *kg; | |
| 89 | − | |
| 90 | 88 | /* |
| 91 | 89 | * We need to make things right with the |
| 92 | 90 | * ABI compatibility. The files were originally |
| @@ -98,25 +96,22 @@ void intel_gt_sysfs_register(struct intel_gt *gt) · 5 unmodified lines | ||
| 98 | 96 | if (gt_is_root(gt)) |
| 99 | 97 | intel_gt_sysfs_pm_init(gt, gt_get_parent_obj(gt)); |
| 100 | 98 | |
| 101 | − kg = kzalloc(sizeof(*kg), GFP_KERNEL); | |
| 102 | − if (!kg) | |
| 99 | + /* init and xfer ownership to sysfs tree */ | |
| 100 | + if (kobject_init_and_add(>->sysfs_gt, &kobj_gt_type, | |
| 101 | + gt->i915->sysfs_gt, "gt%d", gt->info.id)) | |
| 103 | 102 | goto exit_fail; |
| 104 | 103 | |
| 105 | − kobject_init(&kg->base, &kobj_gt_type); | |
| 106 | − kg->gt = gt; | |
| 107 | − | |
| 108 | − /* xfer ownership to sysfs tree */ | |
| 109 | − if (kobject_add(&kg->base, gt->i915->sysfs_gt, "gt%d", gt->info.id)) | |
| 110 | − goto exit_kobj_put; | |
| 111 | − | |
| 112 | − intel_gt_sysfs_pm_init(gt, &kg->base); | |
| 104 | + intel_gt_sysfs_pm_init(gt, >->sysfs_gt); | |
| 113 | 105 | |
| 114 | 106 | return; |
| 115 | 107 | |
| 116 | −exit_kobj_put: | |
| 117 | − kobject_put(&kg->base); | |
| 118 | − | |
| 119 | 108 | exit_fail: |
| 109 | + kobject_put(>->sysfs_gt); | |
| 120 | 110 | drm_warn(>->i915->drm, |
| 121 | 111 | "failed to initialize gt%d sysfs root\n", gt->info.id); |
| 122 | 112 | } |
| 113 | + | |
| 114 | +void intel_gt_sysfs_unregister(struct intel_gt *gt) | |
| 115 | +{ | |
| 116 | + kobject_put(>->sysfs_gt); | |
| 117 | +} | |
| @@ -13,11 +13,6 @@ · 12 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | struct intel_gt; |
| 15 | 15 | |
| 16 | −struct kobj_gt { | |
| 17 | − struct kobject base; | |
| 18 | − struct intel_gt *gt; | |
| 19 | −}; | |
| 20 | − | |
| 21 | 16 | bool is_object_gt(struct kobject *kobj); |
| 22 | 17 | |
| 23 | 18 | struct drm_i915_private *kobj_to_i915(struct kobject *kobj); |
| @@ -28,6 +23,7 @@ intel_gt_create_kobj(struct intel_gt *gt, · 4 unmodified lines | ||
| 28 | 23 | const char *name); |
| 29 | 24 | |
| 30 | 25 | void intel_gt_sysfs_register(struct intel_gt *gt); |
| 26 | +void intel_gt_sysfs_unregister(struct intel_gt *gt); | |
| 31 | 27 | struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev, |
| 32 | 28 | const char *name); |
| 33 | 29 | |
| @@ -224,6 +224,9 @@ struct intel_gt { · 223 unmodified lines | ||
| 224 | 224 | } mocs; |
| 225 | 225 | |
| 226 | 226 | struct intel_pxp pxp; |
| 227 | + | |
| 228 | + /* gt/gtN sysfs */ | |
| 229 | + struct kobject sysfs_gt; | |
| 227 | 230 | }; |
| 228 | 231 | |
| 229 | 232 | enum intel_gt_scratch_field { |
| @@ -156,7 +156,7 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) · 155 unmodified lines | ||
| 156 | 156 | [INTEL_UC_FW_TYPE_GUC] = { blobs_guc, ARRAY_SIZE(blobs_guc) }, |
| 157 | 157 | [INTEL_UC_FW_TYPE_HUC] = { blobs_huc, ARRAY_SIZE(blobs_huc) }, |
| 158 | 158 | }; |
| 159 | − static const struct uc_fw_platform_requirement *fw_blobs; | |
| 159 | + const struct uc_fw_platform_requirement *fw_blobs; | |
| 160 | 160 | enum intel_platform p = INTEL_INFO(i915)->platform; |
| 161 | 161 | u32 fw_count; |
| 162 | 162 | u8 rev = INTEL_REVID(i915); |
| @@ -166,7 +166,14 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj, · 165 unmodified lines | ||
| 166 | 166 | struct device *kdev = kobj_to_dev(kobj); |
| 167 | 167 | struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); |
| 168 | 168 | struct i915_gpu_coredump *gpu; |
| 169 | − ssize_t ret; | |
| 169 | + ssize_t ret = 0; | |
| 170 | + | |
| 171 | + /* | |
| 172 | + * FIXME: Concurrent clients triggering resets and reading + clearing | |
| 173 | + * dumps can cause inconsistent sysfs reads when a user calls in with a | |
| 174 | + * non-zero offset to complete a prior partial read but the | |
| 175 | + * gpu_coredump has been cleared or replaced. | |
| 176 | + */ | |
| 170 | 177 | |
| 171 | 178 | gpu = i915_first_error_state(i915); |
| 172 | 179 | if (IS_ERR(gpu)) { |
| @@ -178,8 +185,10 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj, · 5 unmodified lines | ||
| 178 | 185 | const char *str = "No error state collected\n"; |
| 179 | 186 | size_t len = strlen(str); |
| 180 | 187 | |
| 181 | − ret = min_t(size_t, count, len - off); | |
| 182 | − memcpy(buf, str + off, ret); | |
| 188 | + if (off < len) { | |
| 189 | + ret = min_t(size_t, count, len - off); | |
| 190 | + memcpy(buf, str + off, ret); | |
| 191 | + } | |
| 183 | 192 | } |
| 184 | 193 | |
| 185 | 194 | return ret; |
| @@ -259,4 +268,6 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv) · 73 unmodified lines | ||
| 259 | 268 | |
| 260 | 269 | device_remove_bin_file(kdev, &dpf_attrs_1); |
| 261 | 270 | device_remove_bin_file(kdev, &dpf_attrs); |
| 271 | + | |
| 272 | + kobject_put(dev_priv->sysfs_gt); | |
| 262 | 273 | } |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | */ |
| 24 | 24 | |
| 25 | 25 | #include <linux/sched/mm.h> |
| 26 | +#include <linux/dma-fence-array.h> | |
| 26 | 27 | #include <drm/drm_gem.h> |
| 27 | 28 | |
| 28 | 29 | #include "display/intel_frontbuffer.h" |
| @@ -1823,6 +1824,21 @@ int _i915_vma_move_to_active(struct i915_vma *vma, · 1794 unmodified lines | ||
| 1823 | 1824 | if (unlikely(err)) |
| 1824 | 1825 | return err; |
| 1825 | 1826 | |
| 1827 | + /* | |
| 1828 | + * Reserve fences slot early to prevent an allocation after preparing | |
| 1829 | + * the workload and associating fences with dma_resv. | |
| 1830 | + */ | |
| 1831 | + if (fence && !(flags & __EXEC_OBJECT_NO_RESERVE)) { | |
| 1832 | + struct dma_fence *curr; | |
| 1833 | + int idx; | |
| 1834 | + | |
| 1835 | + dma_fence_array_for_each(curr, idx, fence) | |
| 1836 | + ; | |
| 1837 | + err = dma_resv_reserve_fences(vma->obj->base.resv, idx); | |
| 1838 | + if (unlikely(err)) | |
| 1839 | + return err; | |
| 1840 | + } | |
| 1841 | + | |
| 1826 | 1842 | if (flags & EXEC_OBJECT_WRITE) { |
| 1827 | 1843 | struct intel_frontbuffer *front; |
| 1828 | 1844 | |
| @@ -1832,31 +1848,23 @@ int _i915_vma_move_to_active(struct i915_vma *vma, · 3 unmodified lines | ||
| 1832 | 1848 | i915_active_add_request(&front->write, rq); |
| 1833 | 1849 | intel_frontbuffer_put(front); |
| 1834 | 1850 | } |
| 1851 | + } | |
| 1835 | 1852 | |
| 1836 | − if (!(flags & __EXEC_OBJECT_NO_RESERVE)) { | |
| 1837 | − err = dma_resv_reserve_fences(vma->obj->base.resv, 1); | |
| 1838 | − if (unlikely(err)) | |
| 1839 | − return err; | |
| 1840 | − } | |
| 1853 | + if (fence) { | |
| 1854 | + struct dma_fence *curr; | |
| 1855 | + enum dma_resv_usage usage; | |
| 1856 | + int idx; | |
| 1841 | 1857 | |
| 1842 | − if (fence) { | |
| 1843 | − dma_resv_add_fence(vma->obj->base.resv, fence, | |
| 1844 | − DMA_RESV_USAGE_WRITE); | |
| 1858 | + obj->read_domains = 0; | |
| 1859 | + if (flags & EXEC_OBJECT_WRITE) { | |
| 1860 | + usage = DMA_RESV_USAGE_WRITE; | |
| 1845 | 1861 | obj->write_domain = I915_GEM_DOMAIN_RENDER; |
| 1846 | − obj->read_domains = 0; | |
| 1847 | − } | |
| 1848 | − } else { | |
| 1849 | − if (!(flags & __EXEC_OBJECT_NO_RESERVE)) { | |
| 1850 | − err = dma_resv_reserve_fences(vma->obj->base.resv, 1); | |
| 1851 | − if (unlikely(err)) | |
| 1852 | − return err; | |
| 1862 | + } else { | |
| 1863 | + usage = DMA_RESV_USAGE_READ; | |
| 1853 | 1864 | } |
| 1854 | 1865 | |
| 1855 | − if (fence) { | |
| 1856 | − dma_resv_add_fence(vma->obj->base.resv, fence, | |
| 1857 | − DMA_RESV_USAGE_READ); | |
| 1858 | − obj->write_domain = 0; | |
| 1859 | − } | |
| 1866 | + dma_fence_array_for_each(curr, idx, fence) | |
| 1867 | + dma_resv_add_fence(vma->obj->base.resv, curr, usage); | |
| 1860 | 1868 | } |
| 1861 | 1869 | |
| 1862 | 1870 | if (flags & EXEC_OBJECT_NEEDS_FENCE && vma->fence) |