diff --git a/src/intel/ds/intel_pps_driver.cc b/src/intel/ds/intel_pps_driver.cc index 9cc5c0c2731..cc64c6e166a 100644 --- a/src/intel/ds/intel_pps_driver.cc +++ b/src/intel/ds/intel_pps_driver.cc @@ -253,17 +253,19 @@ void IntelDriver::read_data_from_metric_set() { assert(metric_buffer.size() >= 1024 && "Metric buffer should have space for reading"); - ssize_t bytes_read = 0; - while ((bytes_read = perf->read_oa_stream(metric_buffer.data() + total_bytes_read, - metric_buffer.size() - total_bytes_read)) > 0 || - errno == EINTR) { + do { + ssize_t bytes_read = perf->read_oa_stream(metric_buffer.data() + total_bytes_read, + metric_buffer.size() - total_bytes_read); + if (bytes_read <= 0) + break; + total_bytes_read += std::max(ssize_t(0), bytes_read); // Increase size of the buffer for the next read if (metric_buffer.size() / 2 < total_bytes_read) { metric_buffer.resize(metric_buffer.size() * 2); } - } + } while (true); assert(total_bytes_read < metric_buffer.size() && "Buffer not big enough"); } diff --git a/src/intel/perf/i915/intel_perf.c b/src/intel/perf/i915/intel_perf.c index 66496e14c80..2277b89d0ce 100644 --- a/src/intel/perf/i915/intel_perf.c +++ b/src/intel/perf/i915/intel_perf.c @@ -210,3 +210,25 @@ i915_oa_metrics_available(struct intel_perf_config *perf, int fd, bool use_regis return i915_perf_oa_available; } + +int +i915_perf_stream_read_samples(int perf_stream_fd, uint8_t *buffer, + size_t buffer_len) +{ + int len; + + if (buffer_len < INTEL_PERF_OA_HEADER_SAMPLE_SIZE) + return -ENOSPC; + + do { + len = read(perf_stream_fd, buffer, buffer_len); + } while (len < 0 && errno == EINTR); + + if (len <= 0) + return len < 0 ? -errno : 0; + + /* works as long drm_i915_perf_record_header and intel_perf_record_header + * definition matches + */ + return len; +} diff --git a/src/intel/perf/i915/intel_perf.h b/src/intel/perf/i915/intel_perf.h index cfa3cbde519..81c4e2189f7 100644 --- a/src/intel/perf/i915/intel_perf.h +++ b/src/intel/perf/i915/intel_perf.h @@ -6,6 +6,7 @@ #pragma once #include +#include #include struct intel_perf_config; @@ -17,6 +18,7 @@ int i915_perf_stream_open(struct intel_perf_config *perf_config, int drm_fd, uint32_t ctx_id, uint64_t metrics_set_id, uint64_t report_format, uint64_t period_exponent, bool hold_preemption, bool enable); +int i915_perf_stream_read_samples(int perf_stream_fd, uint8_t *buffer, size_t buffer_len); struct intel_perf_registers *i915_perf_load_configurations(struct intel_perf_config *perf_cfg, int fd, const char *guid); diff --git a/src/intel/perf/intel_perf.c b/src/intel/perf/intel_perf.c index 9c884a695c7..294e6839d09 100644 --- a/src/intel/perf/intel_perf.c +++ b/src/intel/perf/intel_perf.c @@ -1490,3 +1490,25 @@ intel_perf_stream_open(struct intel_perf_config *perf_config, int drm_fd, return 0; } } + +/* + * Read perf stream samples. + * + * buffer will be filled with multiple struct intel_perf_record_header + data. + * + * Returns 0 if no sample is available, -errno value if a error happened or + * the number of bytes read on success. + */ +int +intel_perf_stream_read_samples(struct intel_perf_config *perf_config, + int perf_stream_fd, uint8_t *buffer, + size_t buffer_len) +{ + switch (perf_config->devinfo->kmd_type) { + case INTEL_KMD_TYPE_I915: + return i915_perf_stream_read_samples(perf_stream_fd, buffer, buffer_len); + default: + unreachable("missing"); + return -1; + } +} diff --git a/src/intel/perf/intel_perf.h b/src/intel/perf/intel_perf.h index 625b03104e6..8a85604fa5a 100644 --- a/src/intel/perf/intel_perf.h +++ b/src/intel/perf/intel_perf.h @@ -588,6 +588,9 @@ int intel_perf_stream_open(struct intel_perf_config *perf_config, int drm_fd, uint32_t ctx_id, uint64_t metrics_set_id, uint64_t period_exponent, bool hold_preemption, bool enable); +int intel_perf_stream_read_samples(struct intel_perf_config *perf_config, + int perf_stream_fd, uint8_t *buffer, + size_t buffer_len); #ifdef __cplusplus } // extern "C" diff --git a/src/intel/perf/intel_perf_query.c b/src/intel/perf/intel_perf_query.c index be7fa7d6802..6070809ed0d 100644 --- a/src/intel/perf/intel_perf_query.c +++ b/src/intel/perf/intel_perf_query.c @@ -944,7 +944,8 @@ intel_perf_read_oa_stream(struct intel_perf_context *perf_ctx, void* buf, size_t nbytes) { - return read(perf_ctx->oa_stream_fd, buf, nbytes); + return intel_perf_stream_read_samples(perf_ctx->perf, perf_ctx->oa_stream_fd, + buf, nbytes); } enum OaReadStatus { @@ -971,9 +972,9 @@ read_oa_samples_until(struct intel_perf_context *perf_ctx, uint32_t offset; int len; - while ((len = read(perf_ctx->oa_stream_fd, buf->buf, - sizeof(buf->buf))) < 0 && errno == EINTR) - ; + len = intel_perf_stream_read_samples(perf_ctx->perf, + perf_ctx->oa_stream_fd, + buf->buf, sizeof(buf->buf)); if (len <= 0) { exec_list_push_tail(&perf_ctx->free_sample_buffers, &buf->link); @@ -986,7 +987,7 @@ read_oa_samples_until(struct intel_perf_context *perf_ctx, return OA_READ_STATUS_ERROR; } - if (errno != EAGAIN) { + if (len != -EAGAIN) { if (sample_read) return OA_READ_STATUS_FINISHED;