[igt-dev] [PATCH i-g-t v2 3/7] lib/igt_power: Add hwmon interface to igt_power
Riana Tauro
riana.tauro at intel.com
Wed Sep 14 14:07:17 UTC 2022
Modify igt_power to expose functions to read energy, power
using hwmon and rapl interface
Cc: Ashutosh Dixit <ashutosh.dixit at intel.com>
Signed-off-by: Riana Tauro <riana.tauro at intel.com>
---
lib/igt_power.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/igt_power.h | 22 ++++++++
2 files changed, 153 insertions(+)
diff --git a/lib/igt_power.c b/lib/igt_power.c
index 814ad556..3f3633eb 100644
--- a/lib/igt_power.c
+++ b/lib/igt_power.c
@@ -6,10 +6,14 @@
#include <unistd.h>
#include <inttypes.h>
+#include "igt.h"
+#include "igt_hwmon.h"
#include "igt_perf.h"
#include "igt_power.h"
#include "igt_sysfs.h"
+static const char *rapl_domains[] = { "cpu", "gpu", "pkg", "ram" };
+
static int rapl_parse(struct rapl *r, const char *str)
{
locale_t locale, oldlocale;
@@ -67,3 +71,130 @@ err:
errno = 0;
return r->fd;
}
+
+/**
+ * igt_power_open:
+ * @fd : device fd
+ * @igt_power : power struct
+ * @domain: rapl domain
+ *
+ * opens the hwmon/rapl fd based on domain
+ * hwmon fd - domain gpu -dgfx
+ * rapl fd - all domains - igfx
+ *
+ * Returns
+ * 0 on success, errno otherwise
+ */
+int igt_power_open(int fd, struct igt_power *p, const char *domain)
+{
+ int i;
+
+ p->hwmon_fd = -1;
+ p->rapl.fd = -1;
+
+ if (gem_has_lmem(fd)) {
+ if (strncmp(domain, "gpu", strlen("gpu")) == 0) {
+ p->hwmon_fd = igt_hwmon_open(fd);
+ if (p->hwmon_fd >= 0)
+ return 0;
+ }
+ } else {
+ for (i = 0; i < ARRAY_SIZE(rapl_domains); i++)
+ if (strncmp(domain, rapl_domains[i], strlen(rapl_domains[i])) == 0)
+ return rapl_open(&p->rapl, domain);
+ }
+
+ return -EINVAL;
+}
+
+/**
+ * igt_power_get_energy:
+ * @igt_power : power struct
+ * @power_sample: sample of energy and time
+ *
+ * Reads energy from hwmon if energy1_input file is present, else read
+ * from rapl interface
+ *
+ */
+void igt_power_get_energy(struct igt_power *power, struct power_sample *s)
+{
+ struct timespec ts;
+
+ s->energy = 0;
+ igt_assert(!clock_gettime(CLOCK_MONOTONIC, &ts));
+ s->time = ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
+
+ if (power->hwmon_fd >= 0) {
+ if (igt_sysfs_has_attr(power->hwmon_fd, "energy1_input"))
+ s->energy = igt_sysfs_get_u64(power->hwmon_fd, "energy1_input");
+ } else if (power->rapl.fd >= 0) {
+ rapl_read(&power->rapl, s);
+ }
+}
+
+/**
+ * igt_power_get_mJ:
+ * @igt_power : power struct
+ * @power_sample: sample of energy and time
+ *
+ * Calculates energy difference between two power samples
+ *
+ * Returns
+ * energy in mJ from hwmon/rapl
+ */
+double igt_power_get_mJ(const struct igt_power *power,
+ const struct power_sample *p0, const struct power_sample *p1)
+{
+ if (power->hwmon_fd >= 0)
+ return (p1->energy - p0->energy) * 1e-3;
+ else if (power->rapl.fd >= 0)
+ return ((p1->energy - p0->energy) * power->rapl.scale) * 1e3;
+
+ return 0;
+}
+
+/**
+ * igt_power_get_mW:
+ * @igt_power : power struct
+ * @power_sample: sample of energy and time
+ *
+ * Calculates power
+ *
+ * Returns
+ * power in milliWatts
+ */
+double igt_power_get_mW(const struct igt_power *power,
+ const struct power_sample *p0, const struct power_sample *p1)
+{
+ return igt_power_get_mJ(power, p0, p1) / igt_power_get_s(p0, p1);
+}
+
+/**
+ * igt_power_get_s:
+ * @power_sample: sample of energy and time
+ *
+ * Returns
+ * time differnce in seconds
+ */
+double igt_power_get_s(const struct power_sample *p0,
+ const struct power_sample *p1)
+{
+ return (p1->time - p0->time) * 1e-9;
+}
+
+/**
+ * igt_power_close:
+ * @igt_power : power struct
+ *
+ * closes hwmon/rapl fd
+ *
+ */
+void igt_power_close(struct igt_power *power)
+{
+ if (power->hwmon_fd >= 0) {
+ close(power->hwmon_fd);
+ power->hwmon_fd = -1;
+ } else if (power->rapl.fd >= 0) {
+ rapl_close(&power->rapl);
+ }
+}
diff --git a/lib/igt_power.h b/lib/igt_power.h
index 11ddcdee..0984c2df 100644
--- a/lib/igt_power.h
+++ b/lib/igt_power.h
@@ -39,7 +39,14 @@ struct power_sample {
uint64_t time;
};
+struct igt_power {
+ struct rapl rapl;
+ int hwmon_fd;
+};
+
int rapl_open(struct rapl *r, const char *domain);
+int igt_power_open(int i915, struct igt_power *p, const char *domain);
+void igt_power_close(struct igt_power *p);
static inline int cpu_power_open(struct rapl *r)
{
@@ -77,6 +84,11 @@ static inline void rapl_close(struct rapl *r)
r->fd = -1;
}
+static inline bool igt_power_valid(struct igt_power *p)
+{
+ return (p->rapl.fd >= 0) || (p->hwmon_fd >= 0);
+}
+
static inline double power_J(const struct rapl *r,
const struct power_sample *p0,
const struct power_sample *p1)
@@ -98,4 +110,14 @@ static inline double power_W(const struct rapl *r,
return power_J(r, p0, p1) / power_s(r, p0, p1);
}
+void igt_power_get_energy(struct igt_power *p, struct power_sample *s);
+
+double igt_power_get_mJ(const struct igt_power *power,
+ const struct power_sample *p0,
+ const struct power_sample *p1);
+double igt_power_get_mW(const struct igt_power *power,
+ const struct power_sample *p0,
+ const struct power_sample *p1);
+double igt_power_get_s(const struct power_sample *p0,
+ const struct power_sample *p1);
#endif /* IGT_POWER_H */
--
2.25.1
More information about the igt-dev
mailing list