[igt-dev] [PATCH i-g-t 3/6] lib/igt_power: Add hwmon interface to igt_power

Riana Tauro riana.tauro at intel.com
Tue Sep 6 10:38:15 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 | 144 +++++++++++++++++++++++++++++++++++++++++++++++-
 lib/igt_power.h |  70 ++++++-----------------
 2 files changed, 160 insertions(+), 54 deletions(-)

diff --git a/lib/igt_power.c b/lib/igt_power.c
index 814ad556..3b34be40 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;
@@ -49,7 +53,7 @@ static int rapl_parse(struct rapl *r, const char *str)
 	return 0;
 }
 
-int rapl_open(struct rapl *r, const char *domain)
+static int rapl_open(struct rapl *r, const char *domain)
 {
 	r->fd = rapl_parse(r, domain);
 	if (r->fd < 0)
@@ -67,3 +71,141 @@ err:
 	errno = 0;
 	return r->fd;
 }
+
+static inline bool rapl_read(struct rapl *r, struct power_sample *s)
+{
+	return read(r->fd, s, sizeof(*s)) == sizeof(*s);
+}
+
+static inline void rapl_close(struct rapl *r)
+{
+	close(r->fd);
+	r->fd = -1;
+}
+
+/**
+ * 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..68a05300 100644
--- a/lib/igt_power.h
+++ b/lib/igt_power.h
@@ -39,63 +39,27 @@ struct power_sample {
 	uint64_t time;
 };
 
-int rapl_open(struct rapl *r, const char *domain);
-
-static inline int cpu_power_open(struct rapl *r)
-{
-	return rapl_open(r, "cpu");
-}
-
-static inline int gpu_power_open(struct rapl *r)
-{
-	return rapl_open(r, "gpu");
-}
-
-static inline int pkg_power_open(struct rapl *r)
-{
-	return rapl_open(r, "pkg");
-}
-
-static inline bool rapl_valid(struct rapl *r)
-{
-	return r->fd >= 0;
-}
-
-static inline int ram_power_open(struct rapl *r)
-{
-	return rapl_open(r, "ram");
-}
-
-static inline bool rapl_read(struct rapl *r, struct power_sample *s)
-{
-	return read(r->fd, s, sizeof(*s)) == sizeof(*s);
-}
-
-static inline void rapl_close(struct rapl *r)
-{
-	close(r->fd);
-	r->fd = -1;
-}
+struct igt_power {
+	struct rapl rapl;
+	int hwmon_fd;
+};
 
-static inline double power_J(const struct rapl *r,
-			     const struct power_sample *p0,
-			     const struct power_sample *p1)
-{
-	return (p1->energy - p0->energy) * r->scale;
-}
+int igt_power_open(int i915, struct igt_power *p, const char *domain);
+void igt_power_close(struct igt_power *p);
 
-static inline double power_s(const struct rapl *r,
-			     const struct power_sample *p0,
-			     const struct power_sample *p1)
+static inline bool igt_power_valid(struct igt_power *p)
 {
-	return (p1->time - p0->time) * 1e-9;
+	return (p->rapl.fd >= 0) || (p->hwmon_fd >= 0);
 }
 
-static inline double power_W(const struct rapl *r,
-			     const struct power_sample *p0,
-			     const struct power_sample *p1)
-{
-	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