Applies cleanly but I can't get test it since I don't have a VM setup.

If nobody objects to it in a short while I'll push it through.

Tom

On 13/07/17 12:19 PM, Jean-Francois Thibert wrote:
Running the top command on the PF now allows monitoring activity for
a single VF by using [] keys and also to monitor relative assignment
of each VF.

Signed-off-by: Jean-Francois Thibert <[email protected]>
---
  src/app/top.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
  1 file changed, 205 insertions(+), 10 deletions(-)

diff --git a/src/app/top.c b/src/app/top.c
index 359d241..366302b 100644
--- a/src/app/top.c
+++ b/src/app/top.c
@@ -23,8 +23,9 @@
   *
   */
  #include "umrapp.h"
-#include <time.h>
+#include <linux/pci_regs.h>
  #include <ncurses.h>
+#include <time.h>
static struct {
        int quit,
@@ -48,6 +49,10 @@ static struct {
        } vi;
        char *helptext;
        void (*handle_key)(int ch);
+       struct {
+               int num_vf,
+                   active_vf;
+       } sriov;
  } top_options;
enum sensor_maps {
@@ -70,6 +75,11 @@ enum drm_print {
        DRM_INFO_COUNT,
  };
+enum iov_print {
+       IOV_VF = 0,
+       IOV_PF = 1,
+};
+
  static struct umr_bitfield stat_grbm_bits[] = {
         { "TA_BUSY", 255, 255, &umr_bitfield_default },
         { "GDS_BUSY", 255, 255, &umr_bitfield_default },
@@ -100,6 +110,28 @@ static struct umr_bitfield stat_grbm2_bits[] = {
         { NULL, 0, 0, NULL },
  };
+// The VF virtual bits are remapped from the active VF field
+static struct umr_bitfield stat_rlc_iov_bits[] = {
+        { "VF00", 0, IOV_VF, &umr_bitfield_default },
+        { "VF01", 1, IOV_VF, &umr_bitfield_default },
+        { "VF02", 2, IOV_VF, &umr_bitfield_default },
+        { "VF03", 3, IOV_VF, &umr_bitfield_default },
+        { "VF04", 4, IOV_VF, &umr_bitfield_default },
+        { "VF05", 5, IOV_VF, &umr_bitfield_default },
+        { "VF06", 6, IOV_VF, &umr_bitfield_default },
+        { "VF07", 7, IOV_VF, &umr_bitfield_default },
+        { "VF08", 8, IOV_VF, &umr_bitfield_default },
+        { "VF09", 9, IOV_VF, &umr_bitfield_default },
+        { "VF0A", 10, IOV_VF, &umr_bitfield_default },
+        { "VF0B", 11, IOV_VF, &umr_bitfield_default },
+        { "VF0C", 12, IOV_VF, &umr_bitfield_default },
+        { "VF0D", 13, IOV_VF, &umr_bitfield_default },
+        { "VF0E", 14, IOV_VF, &umr_bitfield_default },
+        { "VF0F", 15, IOV_VF, &umr_bitfield_default },
+        { "PF_VF", 0, IOV_PF, &umr_bitfield_default },
+        { NULL, 0, 0, NULL },
+};
+
  static struct umr_bitfield stat_uvdclk_bits[] = {
         { "UDEC_SCLK", 255, 255, &umr_bitfield_default },
         { "MPEG2_SCLK", 255, 255, &umr_bitfield_default },
@@ -438,6 +470,37 @@ out:
        return (*addr == 0) ? 1 : 0;
  }
+static int grab_addr(char *name, struct umr_asic *asic, struct umr_bitfield *bits, uint32_t *addr)
+{
+       int i, j, k;
+
+       // try to find the register somewhere in the ASIC
+       *addr = 0;
+       for (i = 0; i < asic->no_blocks; i++) {
+               for (j = 0; j < asic->blocks[i]->no_regs; j++) {
+                       if (strcmp(asic->blocks[i]->regs[j].regname, name) == 
0) {
+                               *addr = asic->blocks[i]->regs[j].addr<<2;
+                               goto out;
+                       }
+               }
+       }
+out:
+
+       // let's trim _BUSY out of the names since it's redundant
+       if (*addr) {
+               for (k = 0; bits[k].regname; k++) {
+                       bits[k].regname = strcpy(calloc(1, 
strlen(bits[k].regname) + 1), bits[k].regname);
+                       slice(bits[k].regname, "_BUSY");
+                       slice(bits[k].regname, "_STATUS");
+                       slice(bits[k].regname, "_VALUE");
+                       slice(bits[k].regname, "_ACTIVE");
+                       slice(bits[k].regname, "OUTSTANDING_");
+                       slice(bits[k].regname, "PGFSM_READ_");
+               }
+       }
+       return (*addr == 0) ? 1 : 0;
+}
+
  static int print_j = 0;
static void print_count_value(uint64_t count)
@@ -546,6 +609,21 @@ static void print_drm(struct umr_bitfield *bits, uint64_t 
*counts)
        }
  }
+static void print_iov(uint64_t *counts)
+{
+       int i;
+       for (i = 0; i < top_options.sriov.num_vf; i++) {
+               char custom_namefmt[30];
+               snprintf(custom_namefmt, sizeof(custom_namefmt)-1,
+                       "%%%ds(%%02d) => ", maxstrlen - 3);
+               printw(custom_namefmt, "VF", i);
+               print_count_value(counts[i]);
+               if ((++print_j & (top_options.wide ? 3 : 1)) != 0)
+                       printw(" |");
+               else
+                       printw("\n");
+       }
+}
static void parse_bits(struct umr_asic *asic, uint32_t addr, struct umr_bitfield *bits, uint64_t *counts, uint32_t *mask, uint32_t *cmp, uint64_t addr_mask)
  {
@@ -640,6 +718,34 @@ static void parse_drm(struct umr_asic *asic, uint32_t 
addr, struct umr_bitfield
        }
  }
+static void parse_iov(struct umr_asic *asic, uint32_t addr, struct umr_bitfield *bits, uint64_t *counts, uint32_t *mask, uint32_t *cmp, uint64_t addr_mask)
+{
+       int j;
+       uint32_t value;
+
+       (void)mask;
+       (void)cmp;
+
+       if (addr) {
+               if (addr_mask && asic->fd.mmio < 0) {
+                       value = 0;
+               } else if (!addr_mask && asic->pci.mem) {
+                       value = asic->pci.mem[addr>>2];
+               } else {
+                       lseek(asic->fd.mmio, addr | addr_mask, SEEK_SET);
+                       read(asic->fd.mmio, &value, 4);
+               }
+               for (j = 0; bits[j].regname; j++)
+                       if (bits[j].start != 255) {
+                               if (bits[j].stop == IOV_VF) {
+                                       counts[j] += ((value & 0xF) == 
bits[j].start) ? 1 : 0;
+                               } else {
+                                       counts[j] += (value & 0x80000000) ? 1 : 
0;
+                               }
+                       }
+       }
+}
+
  static void grab_vram(struct umr_asic *asic)
  {
        char name[256];
@@ -804,6 +910,38 @@ static void vi_handle_keys(int i)
        }
  }
+#define PCI_EXT_CAP_BASE 0x100
+#define PCI_EXT_CAP_LIMIT 0x1000
+
+static int sriov_supported_vf(struct umr_asic *asic)
+{
+       int retval = 0;
+       if (!asic->pci.pdevice)
+       return 0;
+       // Verify if the SRIOV capability is listed in the pci device 
configuration
+       pciaddr_t pci_offset = PCI_EXT_CAP_BASE;
+       while (pci_offset && pci_offset < PCI_EXT_CAP_LIMIT)
+       {
+               uint32_t pci_cfg_data;
+               if (pci_device_cfg_read_u32(asic->pci.pdevice, &pci_cfg_data, 
pci_offset))
+                       return 0;
+               if (PCI_EXT_CAP_ID(pci_cfg_data) == PCI_EXT_CAP_ID_SRIOV) {
+                       uint16_t sriov_ctrl;
+                       if (pci_device_cfg_read_u16(asic->pci.pdevice, 
&sriov_ctrl,
+                               pci_offset + PCI_SRIOV_CTRL))
+                               return 0;
+                       uint16_t sriov_num_vf;
+                       if (pci_device_cfg_read_u16(asic->pci.pdevice, 
&sriov_num_vf,
+                               pci_offset + PCI_SRIOV_NUM_VF))
+                               return 0;
+
+                       return (sriov_ctrl & PCI_SRIOV_CTRL_VFE) ? sriov_num_vf 
: 0;
+               }
+               pci_offset = PCI_EXT_CAP_NEXT(pci_cfg_data);
+       }
+       return retval;
+}
+
  static void top_build_vi_program(struct umr_asic *asic)
  {
        int i, j, k;
@@ -820,6 +958,14 @@ static void top_build_vi_program(struct umr_asic *asic)
i = 2; + top_options.sriov.active_vf = -1;
+       top_options.sriov.num_vf = sriov_supported_vf(asic);
+       if (top_options.sriov.num_vf != 0) {
+               stat_counters[i].is_sensor = 3;
+               ENTRY(i++, "mmRLC_GPU_IOV_ACTIVE_FCN_ID", &stat_rlc_iov_bits[0],
+                       &top_options.vi.grbm, "GPU_IOV");
+       }
+
        if (asic->config.gfx.family > 110)
                ENTRY(i++, "mmRLC_GPM_STAT", &stat_rlc_gpm_bits[0], 
&top_options.vi.gfxpwr, "GFX PWR");
@@ -951,6 +1097,22 @@ static uint64_t get_visible_vram_size(struct umr_asic *asic)
        return info.vram_cpu_accessible_size;
  }
+int get_active_vf(struct umr_asic *asic, uint32_t addr)
+{
+       uint32_t value = -1;
+
+       if (addr) {
+               if (asic->pci.mem) {
+                       value = asic->pci.mem[addr>>2];
+               } else {
+                       lseek(asic->fd.mmio, addr, SEEK_SET);
+                       read(asic->fd.mmio, &value, 4);
+               }
+               value &= 0xF;
+       }
+       return value;
+}
+
  void umr_top(struct umr_asic *asic)
  {
        int i, j, k;
@@ -983,9 +1145,12 @@ void umr_top(struct umr_asic *asic)
        ENTRY(i, "DRM", &stat_drm_bits[0], &top_options.drm, "DRM");
        stat_counters[i].is_sensor = 2;
- for (i = 0; stat_counters[i].name; i++)
+       for (i = 0; stat_counters[i].name; i++) {
                if (stat_counters[i].is_sensor == 0)
                        grab_bits(stat_counters[i].name, asic, 
stat_counters[i].bits, &stat_counters[i].addr);
+               else if (stat_counters[i].is_sensor == 3)
+                       grab_addr(stat_counters[i].name, asic, 
stat_counters[i].bits, &stat_counters[i].addr);
+       }
sensor_thread_quit = 0; @@ -1022,15 +1187,21 @@ void umr_top(struct umr_asic *asic)
                        memset(stat_counters[i].counts, 0, 
sizeof(stat_counters[i].counts[0])*32);
for (i = 0; i < (int)rep / (top_options.high_frequency ? 10 : 1); i++) {
-                       for (j = 0; stat_counters[j].name; j++)
-                               if (top_options.all || *stat_counters[j].opt) {
-                                       if (stat_counters[j].is_sensor == 0)
-                                               parse_bits(asic, 
stat_counters[j].addr, stat_counters[j].bits, stat_counters[j].counts, 
stat_counters[j].mask, stat_counters[j].cmp, stat_counters[j].addr_mask);
-                                       else if (i == 0 && 
stat_counters[j].is_sensor == 1) // only parse sensors on first go-around per display
-                                               parse_sensors(asic, 
stat_counters[j].addr, stat_counters[j].bits, stat_counters[j].counts, 
stat_counters[j].mask, stat_counters[j].cmp, stat_counters[j].addr_mask);
-                                       else if (i == 0 && 
stat_counters[j].is_sensor == 2) // only parse drm on first go-around per display
-                                               parse_drm(asic, 
stat_counters[j].addr, stat_counters[j].bits, stat_counters[j].counts, 
stat_counters[j].mask, stat_counters[j].cmp, stat_counters[j].addr_mask);
+                       if (!top_options.sriov.num_vf || 
top_options.sriov.active_vf < 0 ||
+                               top_options.sriov.active_vf == 
get_active_vf(asic, stat_counters[2].addr)) {
+                               for (j = 0; stat_counters[j].name; j++) {
+                                       if (top_options.all || 
*stat_counters[j].opt) {
+                                               if (stat_counters[j].is_sensor 
== 0)
+                                                       parse_bits(asic, 
stat_counters[j].addr, stat_counters[j].bits, stat_counters[j].counts, 
stat_counters[j].mask, stat_counters[j].cmp, stat_counters[j].addr_mask);
+                                               else if (i == 0 && 
stat_counters[j].is_sensor == 1) // only parse sensors on first go-around per display
+                                                       parse_sensors(asic, 
stat_counters[j].addr, stat_counters[j].bits, stat_counters[j].counts, 
stat_counters[j].mask, stat_counters[j].cmp, stat_counters[j].addr_mask);
+                                               else if (i == 0 && 
stat_counters[j].is_sensor == 2) // only parse drm on first go-around per display
+                                                       parse_drm(asic, 
stat_counters[j].addr, stat_counters[j].bits, stat_counters[j].counts, 
stat_counters[j].mask, stat_counters[j].cmp, stat_counters[j].addr_mask);
+                                               else if 
(stat_counters[j].is_sensor == 3)
+                                                       parse_iov(asic, 
stat_counters[j].addr, stat_counters[j].bits, stat_counters[j].counts, 
stat_counters[j].mask, stat_counters[j].cmp, stat_counters[j].addr_mask);
+                                       }
                                }
+                       }
                        nanosleep(&req, NULL);
                        ts += (req.tv_nsec / 1000000);
                }
@@ -1058,6 +1229,25 @@ void umr_top(struct umr_asic *asic)
                        case '2':
                                top_options.high_frequency ^= 1;
                                break;
+                       case '[':
+                               if (top_options.sriov.num_vf) {
+                                       top_options.sriov.active_vf--;
+                                       if (top_options.sriov.active_vf < 0)
+                                               top_options.sriov.active_vf = 
top_options.sriov.num_vf - 1;
+                               }
+                               break;
+                       case ']':
+                               if (top_options.sriov.num_vf) {
+                                       top_options.sriov.active_vf++;
+                                       if (top_options.sriov.active_vf >= 
top_options.sriov.num_vf)
+                                               top_options.sriov.active_vf = 0;
+                               }
+                               break;
+                       case '=':
+                               if (top_options.sriov.num_vf) {
+                                       top_options.sriov.active_vf = -1;
+                               }
+                               break;
                        case 'r': top_options.drm ^= 1; break;
                        default:
                                top_options.handle_key(i);
@@ -1108,6 +1298,8 @@ void umr_top(struct umr_asic *asic)
                                        print_sensors(stat_counters[i].bits, 
stat_counters[i].counts);
                                else if (stat_counters[i].is_sensor == 2)
                                        print_drm(stat_counters[i].bits, 
stat_counters[i].counts);
+                               else if (stat_counters[i].is_sensor == 3)
+                                       print_iov(stat_counters[i].counts);
                        }
                }
                if (logfile != NULL) {
@@ -1123,6 +1315,9 @@ void umr_top(struct umr_asic *asic)
                if (print_j & (top_options.wide ? 3 : 1))
                        printw("\n");
                printw("\n(a)ll (w)ide (1)high_precision (2)high_frequency (W)rite 
(l)ogger\n(v)ram d(r)m\n%s", top_options.helptext);
+               if (top_options.sriov.num_vf) {
+                       printw("([)prev VF (])next VF (=)all VF\n");
+               }
                refresh();
        }
        endwin();


_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to