Skip to content

Commit 06365a0

Browse files
committed
Merge tag 'drm-intel-fixes-2023-09-28' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes
- Fix a panic regression on gen8_ggtt_insert_entries (Matthew Wilcox) - Fix load issue due to reservation address in ggtt_reserve_guc_top (Javier Pello) - Fix a possible deadlock with guc busyness worker (Umesh) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/ZRWMI1HmUYPGGylp@intel.com
2 parents 8c4a5e8 + 907ef03 commit 06365a0

File tree

3 files changed

+59
-13
lines changed

3 files changed

+59
-13
lines changed

drivers/gpu/drm/i915/gem/i915_gem_shmem.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
100100
st->nents = 0;
101101
for (i = 0; i < page_count; i++) {
102102
struct folio *folio;
103+
unsigned long nr_pages;
103104
const unsigned int shrink[] = {
104105
I915_SHRINK_BOUND | I915_SHRINK_UNBOUND,
105106
0,
@@ -150,20 +151,22 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
150151
}
151152
} while (1);
152153

154+
nr_pages = min_t(unsigned long,
155+
folio_nr_pages(folio), page_count - i);
153156
if (!i ||
154157
sg->length >= max_segment ||
155158
folio_pfn(folio) != next_pfn) {
156159
if (i)
157160
sg = sg_next(sg);
158161

159162
st->nents++;
160-
sg_set_folio(sg, folio, folio_size(folio), 0);
163+
sg_set_folio(sg, folio, nr_pages * PAGE_SIZE, 0);
161164
} else {
162165
/* XXX: could overflow? */
163-
sg->length += folio_size(folio);
166+
sg->length += nr_pages * PAGE_SIZE;
164167
}
165-
next_pfn = folio_pfn(folio) + folio_nr_pages(folio);
166-
i += folio_nr_pages(folio) - 1;
168+
next_pfn = folio_pfn(folio) + nr_pages;
169+
i += nr_pages - 1;
167170

168171
/* Check that the i965g/gm workaround works. */
169172
GEM_BUG_ON(gfp & __GFP_DMA32 && next_pfn >= 0x00100000UL);

drivers/gpu/drm/i915/gt/intel_ggtt.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -511,20 +511,31 @@ void intel_ggtt_unbind_vma(struct i915_address_space *vm,
511511
vm->clear_range(vm, vma_res->start, vma_res->vma_size);
512512
}
513513

514+
/*
515+
* Reserve the top of the GuC address space for firmware images. Addresses
516+
* beyond GUC_GGTT_TOP in the GuC address space are inaccessible by GuC,
517+
* which makes for a suitable range to hold GuC/HuC firmware images if the
518+
* size of the GGTT is 4G. However, on a 32-bit platform the size of the GGTT
519+
* is limited to 2G, which is less than GUC_GGTT_TOP, but we reserve a chunk
520+
* of the same size anyway, which is far more than needed, to keep the logic
521+
* in uc_fw_ggtt_offset() simple.
522+
*/
523+
#define GUC_TOP_RESERVE_SIZE (SZ_4G - GUC_GGTT_TOP)
524+
514525
static int ggtt_reserve_guc_top(struct i915_ggtt *ggtt)
515526
{
516-
u64 size;
527+
u64 offset;
517528
int ret;
518529

519530
if (!intel_uc_uses_guc(&ggtt->vm.gt->uc))
520531
return 0;
521532

522-
GEM_BUG_ON(ggtt->vm.total <= GUC_GGTT_TOP);
523-
size = ggtt->vm.total - GUC_GGTT_TOP;
533+
GEM_BUG_ON(ggtt->vm.total <= GUC_TOP_RESERVE_SIZE);
534+
offset = ggtt->vm.total - GUC_TOP_RESERVE_SIZE;
524535

525-
ret = i915_gem_gtt_reserve(&ggtt->vm, NULL, &ggtt->uc_fw, size,
526-
GUC_GGTT_TOP, I915_COLOR_UNEVICTABLE,
527-
PIN_NOEVICT);
536+
ret = i915_gem_gtt_reserve(&ggtt->vm, NULL, &ggtt->uc_fw,
537+
GUC_TOP_RESERVE_SIZE, offset,
538+
I915_COLOR_UNEVICTABLE, PIN_NOEVICT);
528539
if (ret)
529540
drm_dbg(&ggtt->vm.i915->drm,
530541
"Failed to reserve top of GGTT for GuC\n");

drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,6 +1432,36 @@ static void guc_timestamp_ping(struct work_struct *wrk)
14321432
unsigned long index;
14331433
int srcu, ret;
14341434

1435+
/*
1436+
* Ideally the busyness worker should take a gt pm wakeref because the
1437+
* worker only needs to be active while gt is awake. However, the
1438+
* gt_park path cancels the worker synchronously and this complicates
1439+
* the flow if the worker is also running at the same time. The cancel
1440+
* waits for the worker and when the worker releases the wakeref, that
1441+
* would call gt_park and would lead to a deadlock.
1442+
*
1443+
* The resolution is to take the global pm wakeref if runtime pm is
1444+
* already active. If not, we don't need to update the busyness stats as
1445+
* the stats would already be updated when the gt was parked.
1446+
*
1447+
* Note:
1448+
* - We do not requeue the worker if we cannot take a reference to runtime
1449+
* pm since intel_guc_busyness_unpark would requeue the worker in the
1450+
* resume path.
1451+
*
1452+
* - If the gt was parked longer than time taken for GT timestamp to roll
1453+
* over, we ignore those rollovers since we don't care about tracking
1454+
* the exact GT time. We only care about roll overs when the gt is
1455+
* active and running workloads.
1456+
*
1457+
* - There is a window of time between gt_park and runtime suspend,
1458+
* where the worker may run. This is acceptable since the worker will
1459+
* not find any new data to update busyness.
1460+
*/
1461+
wakeref = intel_runtime_pm_get_if_active(&gt->i915->runtime_pm);
1462+
if (!wakeref)
1463+
return;
1464+
14351465
/*
14361466
* Synchronize with gt reset to make sure the worker does not
14371467
* corrupt the engine/guc stats. NB: can't actually block waiting
@@ -1440,10 +1470,9 @@ static void guc_timestamp_ping(struct work_struct *wrk)
14401470
*/
14411471
ret = intel_gt_reset_trylock(gt, &srcu);
14421472
if (ret)
1443-
return;
1473+
goto err_trylock;
14441474

1445-
with_intel_runtime_pm(&gt->i915->runtime_pm, wakeref)
1446-
__update_guc_busyness_stats(guc);
1475+
__update_guc_busyness_stats(guc);
14471476

14481477
/* adjust context stats for overflow */
14491478
xa_for_each(&guc->context_lookup, index, ce)
@@ -1452,6 +1481,9 @@ static void guc_timestamp_ping(struct work_struct *wrk)
14521481
intel_gt_reset_unlock(gt, srcu);
14531482

14541483
guc_enable_busyness_worker(guc);
1484+
1485+
err_trylock:
1486+
intel_runtime_pm_put(&gt->i915->runtime_pm, wakeref);
14551487
}
14561488

14571489
static int guc_action_enable_usage_stats(struct intel_guc *guc)

0 commit comments

Comments
 (0)