Added few more stubs so that control reaches to DestroyDevice().
[mesa.git] / src / freedreno / perfcntrs / fdperf.c
index bf2cecabae925f64322ada0c2d187ee94c00d683..d53828dc0b6f693b7bccb6bc8fb151ba90854d99 100644 (file)
@@ -28,6 +28,7 @@
 #include <err.h>
 #include <fcntl.h>
 #include <ftw.h>
+#include <locale.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -39,6 +40,8 @@
 #include <unistd.h>
 #include <curses.h>
 #include <libconfig.h>
+#include <inttypes.h>
+#include <xf86drm.h>
 
 #include "drm/freedreno_drmif.h"
 #include "drm/freedreno_ringbuffer.h"
@@ -97,6 +100,7 @@ static struct {
 
 static void config_save(void);
 static void config_restore(void);
+static void restore_counter_groups(void);
 
 /*
  * helpers
@@ -120,10 +124,12 @@ readfile(const char *path, int *sz)
                if (ret < 0) {
                        free(buf);
                        *sz = 0;
+                       close(fd);
                        return NULL;
                } else if (ret < CHUNKSIZE) {
                        n += ret;
                        *sz = n;
+                       close(fd);
                        return buf;
                } else {
                        n += CHUNKSIZE;
@@ -149,70 +155,6 @@ delta(uint32_t a, uint32_t b)
                return b - a;
 }
 
-/*
- * TODO de-duplicate OUT_RING() and friends
- */
-
-#define CP_WAIT_FOR_IDLE 38
-#define CP_TYPE0_PKT 0x00000000
-#define CP_TYPE3_PKT 0xc0000000
-#define CP_TYPE4_PKT 0x40000000
-#define CP_TYPE7_PKT 0x70000000
-
-static inline void
-OUT_RING(struct fd_ringbuffer *ring, uint32_t data)
-{
-       *(ring->cur++) = data;
-}
-
-static inline void
-OUT_PKT0(struct fd_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
-{
-       OUT_RING(ring, CP_TYPE0_PKT | ((cnt-1) << 16) | (regindx & 0x7FFF));
-}
-
-static inline void
-OUT_PKT3(struct fd_ringbuffer *ring, uint8_t opcode, uint16_t cnt)
-{
-       OUT_RING(ring, CP_TYPE3_PKT | ((cnt-1) << 16) | ((opcode & 0xFF) << 8));
-}
-
-
-/*
- * Starting with a5xx, pkt4/pkt7 are used instead of pkt0/pkt3
- */
-
-static inline unsigned
-_odd_parity_bit(unsigned val)
-{
-       /* See: http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel
-        * note that we want odd parity so 0x6996 is inverted.
-        */
-       val ^= val >> 16;
-       val ^= val >> 8;
-       val ^= val >> 4;
-       val &= 0xf;
-       return (~0x6996 >> val) & 1;
-}
-
-static inline void
-OUT_PKT4(struct fd_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
-{
-       OUT_RING(ring, CP_TYPE4_PKT | cnt |
-                       (_odd_parity_bit(cnt) << 7) |
-                       ((regindx & 0x3ffff) << 8) |
-                       ((_odd_parity_bit(regindx) << 27)));
-}
-
-static inline void
-OUT_PKT7(struct fd_ringbuffer *ring, uint8_t opcode, uint16_t cnt)
-{
-       OUT_RING(ring, CP_TYPE7_PKT | cnt |
-                       (_odd_parity_bit(cnt) << 15) |
-                       ((opcode & 0x7f) << 16) |
-                       ((_odd_parity_bit(opcode) << 23)));
-}
-
 /*
  * code to find stuff in /proc/device-tree:
  *
@@ -228,7 +170,7 @@ readdt(const char *node)
        void *buf;
        int sz;
 
-       asprintf(&path, "%s/%s", dev.dtnode, node);
+       (void) asprintf(&path, "%s/%s", dev.dtnode, node);
        buf = readfile(path, &sz);
        free(path);
 
@@ -261,7 +203,7 @@ find_freqs(void)
        dev.min_freq = ~0;
        dev.max_freq = 0;
 
-       asprintf(&path, "%s/%s", dev.dtnode, "qcom,gpu-pwrlevels");
+       (void) asprintf(&path, "%s/%s", dev.dtnode, "qcom,gpu-pwrlevels");
 
        ret = nftw(path, find_freqs_fn, 64, 0);
        if (ret < 0)
@@ -270,6 +212,37 @@ find_freqs(void)
        free(path);
 }
 
+static const char * compatibles[] = {
+               "qcom,adreno-3xx",
+               "qcom,kgsl-3d0",
+               "amd,imageon",
+               "qcom,adreno",
+};
+
+/**
+ * compatstrs is a list of compatible strings separated by null, ie.
+ *
+ *       compatible = "qcom,adreno-630.2", "qcom,adreno";
+ *
+ * would result in "qcom,adreno-630.2\0qcom,adreno\0"
+ */
+static bool match_compatible(char *compatstrs, int sz)
+{
+       while (sz > 0) {
+               char *compatible = compatstrs;
+
+               for (unsigned i = 0; i < ARRAY_SIZE(compatibles); i++) {
+                       if (strcmp(compatible, compatibles[i]) == 0) {
+                               return true;
+                       }
+               }
+
+               compatstrs += strlen(compatible) + 1;
+               sz -= strlen(compatible) + 1;
+       }
+       return false;
+}
+
 static int
 find_device_fn(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
 {
@@ -278,9 +251,7 @@ find_device_fn(const char *fpath, const struct stat *sb, int typeflag, struct FT
 
        if (strcmp(fname, "compatible") == 0) {
                char *str = readfile(fpath, &sz);
-               if ((strcmp(str, "qcom,adreno-3xx") == 0) ||
-                               (strcmp(str, "qcom,kgsl-3d0") == 0) ||
-                               (strstr(str, "qcom,adreno") == str)) {
+               if (match_compatible(str, sz)) {
                        int dlen = strlen(fpath) - strlen("/compatible");
                        dev.dtnode = malloc(dlen + 1);
                        memcpy(dev.dtnode, fpath, dlen);
@@ -324,7 +295,7 @@ find_device(void)
        if (!dev.dtnode)
                errx(1, "could not find qcom,adreno-3xx node");
 
-       fd = open("/dev/dri/card0", O_RDWR);
+       fd = drmOpenWithType("msm", NULL, DRM_NODE_RENDER);
        if (fd < 0)
                err(1, "could not open drm device");
 
@@ -368,7 +339,7 @@ find_device(void)
 
        free(b);
 
-       printf("i/o region at %08lx (size: %x)\n", dev.base, dev.size);
+       printf("i/o region at %08"PRIx64" (size: %x)\n", dev.base, dev.size);
 
        /* try MAX_FREQ first as that will work regardless of old dt
         * dt bindings vs upstream bindings:
@@ -389,8 +360,10 @@ find_device(void)
                err(1, "could not open /dev/mem");
 
        dev.io = mmap(0, dev.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, dev.base);
-       if (!dev.io)
+       if (dev.io == MAP_FAILED) {
+               close(fd);
                err(1, "could not map device");
+       }
 }
 
 /*
@@ -439,6 +412,7 @@ select_counter(struct counter_group *group, int ctr, int n)
         */
        struct fd_ringbuffer *ring = dev.ring;
        switch (dev.chipid >> 24) {
+       case 2:
        case 3:
        case 4:
                OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1);
@@ -631,7 +605,7 @@ static void
 redraw_counter_value_raw(WINDOW *win, float val)
 {
        char *str;
-       asprintf(&str, "%'.2f", val);
+       (void) asprintf(&str, "%'.2f", val);
        waddstr(win, str);
        whline(win, ' ', w - getcurx(win));
        free(str);
@@ -863,6 +837,7 @@ static void
 main_ui(void)
 {
        WINDOW *mainwin;
+       uint32_t last_time = gettime_us();
 
        /* curses setup: */
        mainwin = initscr();
@@ -907,6 +882,16 @@ main_ui(void)
                }
                resample();
                redraw(mainwin);
+
+               /* restore the counters every 0.5s in case the GPU has suspended,
+                * in which case the current selected countables will have reset:
+                */
+               uint32_t t = gettime_us();
+               if (delta(last_time, t) > 500000) {
+                       restore_counter_groups();
+                       flush_ring();
+                       last_time = t;
+               }
        }
 
        /* restore settings.. maybe we need an atexit()??*/
@@ -916,6 +901,23 @@ out:
        refresh();
 }
 
+static void
+restore_counter_groups(void)
+{
+       for (unsigned i = 0; i < dev.ngroups; i++) {
+               struct counter_group *group = &dev.groups[i];
+               unsigned j = 0;
+
+               /* NOTE skip CP the first CP counter */
+               if (i == 0)
+                       j++;
+
+               for (; j < group->group->num_counters; j++) {
+                       select_counter(group, j, group->counter[j].select_val);
+               }
+       }
+}
+
 static void
 setup_counter_groups(const struct fd_perfcntr_group *groups)
 {
@@ -939,7 +941,7 @@ setup_counter_groups(const struct fd_perfcntr_group *groups)
                        group->counter[j].val_hi = dev.io + (group->counter[j].counter->counter_reg_hi * 4);
                        group->counter[j].val_lo = dev.io + (group->counter[j].counter->counter_reg_lo * 4);
 
-                       select_counter(group, j, j);
+                       group->counter[j].select_val = j;
                }
 
                for (unsigned j = 0; j < group->group->num_countables; j++) {
@@ -996,7 +998,7 @@ config_restore(void)
        config_setting_t *root = config_root_setting(&cfg);
 
        /* per device settings: */
-       asprintf(&str, "a%dxx", dev.chipid >> 24);
+       (void) asprintf(&str, "a%dxx", dev.chipid >> 24);
        setting = config_setting_get_member(root, str);
        if (!setting)
                setting = config_setting_add(root, str, CONFIG_TYPE_GROUP);
@@ -1048,7 +1050,10 @@ main(int argc, char **argv)
 
        dev.groups = calloc(dev.ngroups, sizeof(struct counter_group));
 
+       setlocale(LC_NUMERIC, "en_US.UTF-8");
+
        setup_counter_groups(groups);
+       restore_counter_groups();
        config_restore();
        flush_ring();