Skip to content

Commit 9e0590e

Browse files
harishchegondiashutoshx
authored andcommitted
drm/xe/eustall: Add support to handle dropped EU stall data
If the user space doesn't read the EU stall data fast enough, it is possible that the EU stall data buffer can get filled, and if the hardware wants to write more data, it simply drops data due to unavailable buffer space. In that case, hardware sets a bit in a register. If the driver detects data drop, the driver read() returns -EIO error to let the user space know that HW has dropped data. The -EIO error is returned even if there is EU stall data in the buffer. A subsequent read by the user space returns the remaining EU stall data. v12: Move 'goto exit_drop;' to the next 'if (read_data_size == 0)' statement. v11: Clear drop bit even for empty data buffer as the data was read from the buffer in the previous read. v10: Reverted the changes back to v8: Clear the drop bits only after reading the data. v9: Move all data drop handling code to this patch Clear all drop data bits before returning -EIO. Reviewed-by: Ashutosh Dixit <[email protected]> Signed-off-by: Harish Chegondi <[email protected]> Signed-off-by: Ashutosh Dixit <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/6fbfd7cfa42cb3ef5515b6412573d74c7cd3d27a.1740533885.git.harish.chegondi@intel.com
1 parent 760edec commit 9e0590e

File tree

1 file changed

+45
-1
lines changed

1 file changed

+45
-1
lines changed

drivers/gpu/drm/xe/xe_eu_stall.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ struct xe_eu_stall_data_stream {
5151
struct xe_gt *gt;
5252
struct xe_bo *bo;
5353
struct per_xecore_buf *xecore_buf;
54+
struct {
55+
bool reported_to_user;
56+
xe_dss_mask_t mask;
57+
} data_drop;
5458
struct delayed_work buf_poll_work;
5559
};
5660

@@ -330,13 +334,25 @@ static bool eu_stall_data_buf_poll(struct xe_eu_stall_data_stream *stream)
330334
if (num_data_rows(total_data) >= stream->wait_num_reports)
331335
min_data_present = true;
332336
}
337+
if (write_ptr_reg & XEHPC_EUSTALL_REPORT_OVERFLOW_DROP)
338+
set_bit(xecore, stream->data_drop.mask);
333339
xecore_buf->write = write_ptr;
334340
}
335341
mutex_unlock(&gt->eu_stall->stream_lock);
336342

337343
return min_data_present;
338344
}
339345

346+
static void clear_dropped_eviction_line_bit(struct xe_gt *gt, u16 group, u16 instance)
347+
{
348+
u32 write_ptr_reg;
349+
350+
/* On PVC, the overflow bit has to be cleared by writing 1 to it. */
351+
write_ptr_reg = _MASKED_BIT_ENABLE(XEHPC_EUSTALL_REPORT_OVERFLOW_DROP);
352+
353+
xe_gt_mcr_unicast_write(gt, XEHPC_EUSTALL_REPORT, write_ptr_reg, group, instance);
354+
}
355+
340356
static int xe_eu_stall_data_buf_read(struct xe_eu_stall_data_stream *stream,
341357
char __user *buf, size_t count,
342358
size_t *total_data_size, struct xe_gt *gt,
@@ -365,7 +381,7 @@ static int xe_eu_stall_data_buf_read(struct xe_eu_stall_data_stream *stream,
365381
/* Read only the data that the user space buffer can accommodate */
366382
read_data_size = min_t(size_t, count - *total_data_size, read_data_size);
367383
if (read_data_size == 0)
368-
return 0;
384+
goto exit_drop;
369385

370386
read_offset = read_ptr & (buf_size - 1);
371387
write_offset = write_ptr & (buf_size - 1);
@@ -397,6 +413,15 @@ static int xe_eu_stall_data_buf_read(struct xe_eu_stall_data_stream *stream,
397413
xecore_buf->read = read_ptr;
398414
trace_xe_eu_stall_data_read(group, instance, read_ptr, write_ptr,
399415
read_data_size, *total_data_size);
416+
exit_drop:
417+
/* Clear drop bit (if set) after any data was read or if the buffer was empty.
418+
* Drop bit can be set even if the buffer is empty as the buffer may have been emptied
419+
* in the previous read() and the data drop bit was set during the previous read().
420+
*/
421+
if (test_bit(xecore, stream->data_drop.mask)) {
422+
clear_dropped_eviction_line_bit(gt, group, instance);
423+
clear_bit(xecore, stream->data_drop.mask);
424+
}
400425
return 0;
401426
}
402427

@@ -422,6 +447,16 @@ static ssize_t xe_eu_stall_stream_read_locked(struct xe_eu_stall_data_stream *st
422447
unsigned int xecore;
423448
int ret = 0;
424449

450+
if (bitmap_weight(stream->data_drop.mask, XE_MAX_DSS_FUSE_BITS)) {
451+
if (!stream->data_drop.reported_to_user) {
452+
stream->data_drop.reported_to_user = true;
453+
xe_gt_dbg(gt, "EU stall data dropped in XeCores: %*pb\n",
454+
XE_MAX_DSS_FUSE_BITS, stream->data_drop.mask);
455+
return -EIO;
456+
}
457+
stream->data_drop.reported_to_user = false;
458+
}
459+
425460
for_each_dss_steering(xecore, gt, group, instance) {
426461
ret = xe_eu_stall_data_buf_read(stream, buf, count, &total_size,
427462
gt, group, instance, xecore);
@@ -434,6 +469,9 @@ static ssize_t xe_eu_stall_stream_read_locked(struct xe_eu_stall_data_stream *st
434469
/*
435470
* Userspace must enable the EU stall stream with DRM_XE_OBSERVATION_IOCTL_ENABLE
436471
* before calling read().
472+
*
473+
* Returns: The number of bytes copied or a negative error code on failure.
474+
* -EIO if HW drops any EU stall data when the buffer is full.
437475
*/
438476
static ssize_t xe_eu_stall_stream_read(struct file *file, char __user *buf,
439477
size_t count, loff_t *ppos)
@@ -538,6 +576,9 @@ static int xe_eu_stall_stream_enable(struct xe_eu_stall_data_stream *stream)
538576

539577
for_each_dss_steering(xecore, gt, group, instance) {
540578
write_ptr_reg = xe_gt_mcr_unicast_read(gt, XEHPC_EUSTALL_REPORT, group, instance);
579+
/* Clear any drop bits set and not cleared in the previous session. */
580+
if (write_ptr_reg & XEHPC_EUSTALL_REPORT_OVERFLOW_DROP)
581+
clear_dropped_eviction_line_bit(gt, group, instance);
541582
write_ptr = REG_FIELD_GET(XEHPC_EUSTALL_REPORT_WRITE_PTR_MASK, write_ptr_reg);
542583
read_ptr_reg = REG_FIELD_PREP(XEHPC_EUSTALL_REPORT1_READ_PTR_MASK, write_ptr);
543584
read_ptr_reg = _MASKED_FIELD(XEHPC_EUSTALL_REPORT1_READ_PTR_MASK, read_ptr_reg);
@@ -549,6 +590,9 @@ static int xe_eu_stall_stream_enable(struct xe_eu_stall_data_stream *stream)
549590
xecore_buf->write = write_ptr;
550591
xecore_buf->read = write_ptr;
551592
}
593+
stream->data_drop.reported_to_user = false;
594+
bitmap_zero(stream->data_drop.mask, XE_MAX_DSS_FUSE_BITS);
595+
552596
reg_value = _MASKED_FIELD(EUSTALL_MOCS | EUSTALL_SAMPLE_RATE,
553597
REG_FIELD_PREP(EUSTALL_MOCS, gt->mocs.uc_index << 1) |
554598
REG_FIELD_PREP(EUSTALL_SAMPLE_RATE,

0 commit comments

Comments
 (0)