mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
Two new data source fields, to indicate the block reasons of a load instruction, are introduced on the Intel Sapphire Rapids server. The fields can be used by the memory profiling. Add a new sort function, SORT_MEM_BLOCKED, for the two fields. For the previous platforms or the block reason is unknown, print "N/A" for the block reason. Add blocked as a default mem sort key for perf report and perf mem report. Committer testing: So in machines without this capability we get a "N/A" filling the new "Blocked" column: $ perf mem record ls arch certs CREDITS Documentation include ipc Kconfig lib MAINTAINERS mm samples security usr block COPYING crypto drivers fs init Kbuild kernel LICENSES Makefile net README scripts sound tools virt [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.008 MB perf.data (17 samples) ] $ $ perf mem report --stdio # To display the perf.data header info, please use --header/--header-only options. # # Total Lost Samples: 0 # # Samples: 6 of event 'cpu/mem-loads,ldlat=30/Pu' # Total weight : 1381 # Sort order : local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked,blocked # # Overhead Samples Local Weight Memory access Symbol Shared Object Data Symbol Data Object Snoop TLB access Locked Blocked # ........ ....... ............ .................... ....................... ............. ...................... ............ ..... ............ ...... ....... # 32.87% 1 454 Local RAM or RAM hit [.] _dl_relocate_object ld-2.31.so [.] 0x00007fe91cef3078 libc-2.31.so Hit L1 or L2 hit No N/A 25.56% 1 353 LFB or LFB hit [.] strcmp ld-2.31.so [.] 0x00005586973855ca ls None L1 or L2 hit No N/A 22.59% 1 312 LFB or LFB hit [.] _dl_cache_libcmp ld-2.31.so [.] 0x00007fe91d0e3b18 ld.so.cache None L1 or L2 hit No N/A 8.47% 1 117 LFB or LFB hit [.] _dl_relocate_object ld-2.31.so [.] 0x00007fe91ceee570 libc-2.31.so None L1 or L2 hit No N/A 6.88% 1 95 LFB or LFB hit [.] _dl_relocate_object ld-2.31.so [.] 0x00007fe91ceed490 libc-2.31.so None L1 or L2 hit No N/A 3.62% 1 50 LFB or LFB hit [.] _dl_cache_libcmp ld-2.31.so [.] 0x00007fe91d0ebe60 ld.so.cache None L1 or L2 hit No N/A # Samples: 11 of event 'cpu/mem-stores/Pu' # Total weight : 11 # Sort order : local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked,blocked # # Overhead Samples Local Weight Memory access Symbol Shared Object Data Symbol Data Object Snoop TLB access Locked Blocked # ........ ....... ............ ............. ....................... ............. ...................... ........... ..... .......... ...... ....... # 9.09% 1 0 L1 hit [.] __strcoll_l libc-2.31.so [.] 0x00007fffe5648fc8 [stack] N/A N/A N/A N/A 9.09% 1 0 L1 hit [.] _dl_lookup_symbol_x ld-2.31.so [.] 0x00007fffe56490b8 [stack] N/A N/A N/A N/A 9.09% 1 0 L1 hit [.] _dl_name_match_p ld-2.31.so [.] 0x00007fffe56487d8 [stack] N/A N/A N/A N/A 9.09% 1 0 L1 hit [.] _dl_start ld-2.31.so [.] start_time+0x0 ld-2.31.so N/A N/A N/A N/A 9.09% 1 0 L1 hit [.] _dl_sysdep_start ld-2.31.so [.] 0x00007fffe56494b8 [stack] N/A N/A N/A N/A 9.09% 1 0 L1 hit [.] do_lookup_x ld-2.31.so [.] 0x00007fffe5648ff8 [stack] N/A N/A N/A N/A 9.09% 1 0 L1 hit [.] do_lookup_x ld-2.31.so [.] 0x00007fffe5649064 [stack] N/A N/A N/A N/A 9.09% 1 0 L1 hit [.] do_lookup_x ld-2.31.so [.] 0x00007fffe5649130 [stack] N/A N/A N/A N/A 9.09% 1 0 L1 miss [.] _dl_start ld-2.31.so [.] _rtld_global+0xaf8 ld-2.31.so N/A N/A N/A N/A 9.09% 1 0 L1 miss [.] _dl_start ld-2.31.so [.] _rtld_global+0xc28 ld-2.31.so N/A N/A N/A N/A 9.09% 1 0 L1 miss [.] _dl_start ld-2.31.so [.] 0x00007fffe56495b8 [stack] N/A N/A N/A N/A # (Tip: Show user configuration overrides: perf config --user --list) $ Signed-off-by: Kan Liang <kan.liang@linux.intel.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Jin Yao <yao.jin@linux.intel.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Madhavan Srinivasan <maddy@linux.vnet.ibm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lore.kernel.org/lkml/1612296553-21962-4-git-send-email-kan.liang@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
521 lines
11 KiB
C
521 lines
11 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <api/fs/fs.h>
|
|
#include <linux/kernel.h>
|
|
#include "map_symbol.h"
|
|
#include "mem-events.h"
|
|
#include "debug.h"
|
|
#include "symbol.h"
|
|
|
|
unsigned int perf_mem_events__loads_ldlat = 30;
|
|
|
|
#define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
|
|
|
|
static struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
|
|
E("ldlat-loads", "cpu/mem-loads,ldlat=%u/P", "cpu/events/mem-loads"),
|
|
E("ldlat-stores", "cpu/mem-stores/P", "cpu/events/mem-stores"),
|
|
E(NULL, NULL, NULL),
|
|
};
|
|
#undef E
|
|
|
|
#undef E
|
|
|
|
static char mem_loads_name[100];
|
|
static bool mem_loads_name__init;
|
|
|
|
struct perf_mem_event * __weak perf_mem_events__ptr(int i)
|
|
{
|
|
if (i >= PERF_MEM_EVENTS__MAX)
|
|
return NULL;
|
|
|
|
return &perf_mem_events[i];
|
|
}
|
|
|
|
char * __weak perf_mem_events__name(int i)
|
|
{
|
|
struct perf_mem_event *e = perf_mem_events__ptr(i);
|
|
|
|
if (!e)
|
|
return NULL;
|
|
|
|
if (i == PERF_MEM_EVENTS__LOAD) {
|
|
if (!mem_loads_name__init) {
|
|
mem_loads_name__init = true;
|
|
scnprintf(mem_loads_name, sizeof(mem_loads_name),
|
|
e->name, perf_mem_events__loads_ldlat);
|
|
}
|
|
return mem_loads_name;
|
|
}
|
|
|
|
return (char *)e->name;
|
|
}
|
|
|
|
__weak bool is_mem_loads_aux_event(struct evsel *leader __maybe_unused)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int perf_mem_events__parse(const char *str)
|
|
{
|
|
char *tok, *saveptr = NULL;
|
|
bool found = false;
|
|
char *buf;
|
|
int j;
|
|
|
|
/* We need buffer that we know we can write to. */
|
|
buf = malloc(strlen(str) + 1);
|
|
if (!buf)
|
|
return -ENOMEM;
|
|
|
|
strcpy(buf, str);
|
|
|
|
tok = strtok_r((char *)buf, ",", &saveptr);
|
|
|
|
while (tok) {
|
|
for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
|
|
struct perf_mem_event *e = perf_mem_events__ptr(j);
|
|
|
|
if (!e->tag)
|
|
continue;
|
|
|
|
if (strstr(e->tag, tok))
|
|
e->record = found = true;
|
|
}
|
|
|
|
tok = strtok_r(NULL, ",", &saveptr);
|
|
}
|
|
|
|
free(buf);
|
|
|
|
if (found)
|
|
return 0;
|
|
|
|
pr_err("failed: event '%s' not found, use '-e list' to get list of available events\n", str);
|
|
return -1;
|
|
}
|
|
|
|
int perf_mem_events__init(void)
|
|
{
|
|
const char *mnt = sysfs__mount();
|
|
bool found = false;
|
|
int j;
|
|
|
|
if (!mnt)
|
|
return -ENOENT;
|
|
|
|
for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
|
|
char path[PATH_MAX];
|
|
struct perf_mem_event *e = perf_mem_events__ptr(j);
|
|
struct stat st;
|
|
|
|
/*
|
|
* If the event entry isn't valid, skip initialization
|
|
* and "e->supported" will keep false.
|
|
*/
|
|
if (!e->tag)
|
|
continue;
|
|
|
|
scnprintf(path, PATH_MAX, "%s/devices/%s",
|
|
mnt, e->sysfs_name);
|
|
|
|
if (!stat(path, &st))
|
|
e->supported = found = true;
|
|
}
|
|
|
|
return found ? 0 : -ENOENT;
|
|
}
|
|
|
|
void perf_mem_events__list(void)
|
|
{
|
|
int j;
|
|
|
|
for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
|
|
struct perf_mem_event *e = perf_mem_events__ptr(j);
|
|
|
|
fprintf(stderr, "%-13s%-*s%s\n",
|
|
e->tag ?: "",
|
|
verbose > 0 ? 25 : 0,
|
|
verbose > 0 ? perf_mem_events__name(j) : "",
|
|
e->supported ? ": available" : "");
|
|
}
|
|
}
|
|
|
|
static const char * const tlb_access[] = {
|
|
"N/A",
|
|
"HIT",
|
|
"MISS",
|
|
"L1",
|
|
"L2",
|
|
"Walker",
|
|
"Fault",
|
|
};
|
|
|
|
int perf_mem__tlb_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
|
|
{
|
|
size_t l = 0, i;
|
|
u64 m = PERF_MEM_TLB_NA;
|
|
u64 hit, miss;
|
|
|
|
sz -= 1; /* -1 for null termination */
|
|
out[0] = '\0';
|
|
|
|
if (mem_info)
|
|
m = mem_info->data_src.mem_dtlb;
|
|
|
|
hit = m & PERF_MEM_TLB_HIT;
|
|
miss = m & PERF_MEM_TLB_MISS;
|
|
|
|
/* already taken care of */
|
|
m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
|
|
|
|
for (i = 0; m && i < ARRAY_SIZE(tlb_access); i++, m >>= 1) {
|
|
if (!(m & 0x1))
|
|
continue;
|
|
if (l) {
|
|
strcat(out, " or ");
|
|
l += 4;
|
|
}
|
|
l += scnprintf(out + l, sz - l, tlb_access[i]);
|
|
}
|
|
if (*out == '\0')
|
|
l += scnprintf(out, sz - l, "N/A");
|
|
if (hit)
|
|
l += scnprintf(out + l, sz - l, " hit");
|
|
if (miss)
|
|
l += scnprintf(out + l, sz - l, " miss");
|
|
|
|
return l;
|
|
}
|
|
|
|
static const char * const mem_lvl[] = {
|
|
"N/A",
|
|
"HIT",
|
|
"MISS",
|
|
"L1",
|
|
"LFB",
|
|
"L2",
|
|
"L3",
|
|
"Local RAM",
|
|
"Remote RAM (1 hop)",
|
|
"Remote RAM (2 hops)",
|
|
"Remote Cache (1 hop)",
|
|
"Remote Cache (2 hops)",
|
|
"I/O",
|
|
"Uncached",
|
|
};
|
|
|
|
static const char * const mem_lvlnum[] = {
|
|
[PERF_MEM_LVLNUM_ANY_CACHE] = "Any cache",
|
|
[PERF_MEM_LVLNUM_LFB] = "LFB",
|
|
[PERF_MEM_LVLNUM_RAM] = "RAM",
|
|
[PERF_MEM_LVLNUM_PMEM] = "PMEM",
|
|
[PERF_MEM_LVLNUM_NA] = "N/A",
|
|
};
|
|
|
|
int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
|
|
{
|
|
size_t i, l = 0;
|
|
u64 m = PERF_MEM_LVL_NA;
|
|
u64 hit, miss;
|
|
int printed;
|
|
|
|
if (mem_info)
|
|
m = mem_info->data_src.mem_lvl;
|
|
|
|
sz -= 1; /* -1 for null termination */
|
|
out[0] = '\0';
|
|
|
|
hit = m & PERF_MEM_LVL_HIT;
|
|
miss = m & PERF_MEM_LVL_MISS;
|
|
|
|
/* already taken care of */
|
|
m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
|
|
|
|
|
|
if (mem_info && mem_info->data_src.mem_remote) {
|
|
strcat(out, "Remote ");
|
|
l += 7;
|
|
}
|
|
|
|
printed = 0;
|
|
for (i = 0; m && i < ARRAY_SIZE(mem_lvl); i++, m >>= 1) {
|
|
if (!(m & 0x1))
|
|
continue;
|
|
if (printed++) {
|
|
strcat(out, " or ");
|
|
l += 4;
|
|
}
|
|
l += scnprintf(out + l, sz - l, mem_lvl[i]);
|
|
}
|
|
|
|
if (mem_info && mem_info->data_src.mem_lvl_num) {
|
|
int lvl = mem_info->data_src.mem_lvl_num;
|
|
if (printed++) {
|
|
strcat(out, " or ");
|
|
l += 4;
|
|
}
|
|
if (mem_lvlnum[lvl])
|
|
l += scnprintf(out + l, sz - l, mem_lvlnum[lvl]);
|
|
else
|
|
l += scnprintf(out + l, sz - l, "L%d", lvl);
|
|
}
|
|
|
|
if (l == 0)
|
|
l += scnprintf(out + l, sz - l, "N/A");
|
|
if (hit)
|
|
l += scnprintf(out + l, sz - l, " hit");
|
|
if (miss)
|
|
l += scnprintf(out + l, sz - l, " miss");
|
|
|
|
return l;
|
|
}
|
|
|
|
static const char * const snoop_access[] = {
|
|
"N/A",
|
|
"None",
|
|
"Hit",
|
|
"Miss",
|
|
"HitM",
|
|
};
|
|
|
|
int perf_mem__snp_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
|
|
{
|
|
size_t i, l = 0;
|
|
u64 m = PERF_MEM_SNOOP_NA;
|
|
|
|
sz -= 1; /* -1 for null termination */
|
|
out[0] = '\0';
|
|
|
|
if (mem_info)
|
|
m = mem_info->data_src.mem_snoop;
|
|
|
|
for (i = 0; m && i < ARRAY_SIZE(snoop_access); i++, m >>= 1) {
|
|
if (!(m & 0x1))
|
|
continue;
|
|
if (l) {
|
|
strcat(out, " or ");
|
|
l += 4;
|
|
}
|
|
l += scnprintf(out + l, sz - l, snoop_access[i]);
|
|
}
|
|
if (mem_info &&
|
|
(mem_info->data_src.mem_snoopx & PERF_MEM_SNOOPX_FWD)) {
|
|
if (l) {
|
|
strcat(out, " or ");
|
|
l += 4;
|
|
}
|
|
l += scnprintf(out + l, sz - l, "Fwd");
|
|
}
|
|
|
|
if (*out == '\0')
|
|
l += scnprintf(out, sz - l, "N/A");
|
|
|
|
return l;
|
|
}
|
|
|
|
int perf_mem__lck_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
|
|
{
|
|
u64 mask = PERF_MEM_LOCK_NA;
|
|
int l;
|
|
|
|
if (mem_info)
|
|
mask = mem_info->data_src.mem_lock;
|
|
|
|
if (mask & PERF_MEM_LOCK_NA)
|
|
l = scnprintf(out, sz, "N/A");
|
|
else if (mask & PERF_MEM_LOCK_LOCKED)
|
|
l = scnprintf(out, sz, "Yes");
|
|
else
|
|
l = scnprintf(out, sz, "No");
|
|
|
|
return l;
|
|
}
|
|
|
|
int perf_mem__blk_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
|
|
{
|
|
size_t l = 0;
|
|
u64 mask = PERF_MEM_BLK_NA;
|
|
|
|
sz -= 1; /* -1 for null termination */
|
|
out[0] = '\0';
|
|
|
|
if (mem_info)
|
|
mask = mem_info->data_src.mem_blk;
|
|
|
|
if (!mask || (mask & PERF_MEM_BLK_NA)) {
|
|
l += scnprintf(out + l, sz - l, " N/A");
|
|
return l;
|
|
}
|
|
if (mask & PERF_MEM_BLK_DATA)
|
|
l += scnprintf(out + l, sz - l, " Data");
|
|
if (mask & PERF_MEM_BLK_ADDR)
|
|
l += scnprintf(out + l, sz - l, " Addr");
|
|
|
|
return l;
|
|
}
|
|
|
|
int perf_script__meminfo_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
|
|
{
|
|
int i = 0;
|
|
|
|
i += perf_mem__lvl_scnprintf(out, sz, mem_info);
|
|
i += scnprintf(out + i, sz - i, "|SNP ");
|
|
i += perf_mem__snp_scnprintf(out + i, sz - i, mem_info);
|
|
i += scnprintf(out + i, sz - i, "|TLB ");
|
|
i += perf_mem__tlb_scnprintf(out + i, sz - i, mem_info);
|
|
i += scnprintf(out + i, sz - i, "|LCK ");
|
|
i += perf_mem__lck_scnprintf(out + i, sz - i, mem_info);
|
|
i += scnprintf(out + i, sz - i, "|BLK ");
|
|
i += perf_mem__blk_scnprintf(out + i, sz - i, mem_info);
|
|
|
|
return i;
|
|
}
|
|
|
|
int c2c_decode_stats(struct c2c_stats *stats, struct mem_info *mi)
|
|
{
|
|
union perf_mem_data_src *data_src = &mi->data_src;
|
|
u64 daddr = mi->daddr.addr;
|
|
u64 op = data_src->mem_op;
|
|
u64 lvl = data_src->mem_lvl;
|
|
u64 snoop = data_src->mem_snoop;
|
|
u64 lock = data_src->mem_lock;
|
|
/*
|
|
* Skylake might report unknown remote level via this
|
|
* bit, consider it when evaluating remote HITMs.
|
|
*/
|
|
bool mrem = data_src->mem_remote;
|
|
int err = 0;
|
|
|
|
#define HITM_INC(__f) \
|
|
do { \
|
|
stats->__f++; \
|
|
stats->tot_hitm++; \
|
|
} while (0)
|
|
|
|
#define P(a, b) PERF_MEM_##a##_##b
|
|
|
|
stats->nr_entries++;
|
|
|
|
if (lock & P(LOCK, LOCKED)) stats->locks++;
|
|
|
|
if (op & P(OP, LOAD)) {
|
|
/* load */
|
|
stats->load++;
|
|
|
|
if (!daddr) {
|
|
stats->ld_noadrs++;
|
|
return -1;
|
|
}
|
|
|
|
if (lvl & P(LVL, HIT)) {
|
|
if (lvl & P(LVL, UNC)) stats->ld_uncache++;
|
|
if (lvl & P(LVL, IO)) stats->ld_io++;
|
|
if (lvl & P(LVL, LFB)) stats->ld_fbhit++;
|
|
if (lvl & P(LVL, L1 )) stats->ld_l1hit++;
|
|
if (lvl & P(LVL, L2 )) stats->ld_l2hit++;
|
|
if (lvl & P(LVL, L3 )) {
|
|
if (snoop & P(SNOOP, HITM))
|
|
HITM_INC(lcl_hitm);
|
|
else
|
|
stats->ld_llchit++;
|
|
}
|
|
|
|
if (lvl & P(LVL, LOC_RAM)) {
|
|
stats->lcl_dram++;
|
|
if (snoop & P(SNOOP, HIT))
|
|
stats->ld_shared++;
|
|
else
|
|
stats->ld_excl++;
|
|
}
|
|
|
|
if ((lvl & P(LVL, REM_RAM1)) ||
|
|
(lvl & P(LVL, REM_RAM2)) ||
|
|
mrem) {
|
|
stats->rmt_dram++;
|
|
if (snoop & P(SNOOP, HIT))
|
|
stats->ld_shared++;
|
|
else
|
|
stats->ld_excl++;
|
|
}
|
|
}
|
|
|
|
if ((lvl & P(LVL, REM_CCE1)) ||
|
|
(lvl & P(LVL, REM_CCE2)) ||
|
|
mrem) {
|
|
if (snoop & P(SNOOP, HIT))
|
|
stats->rmt_hit++;
|
|
else if (snoop & P(SNOOP, HITM))
|
|
HITM_INC(rmt_hitm);
|
|
}
|
|
|
|
if ((lvl & P(LVL, MISS)))
|
|
stats->ld_miss++;
|
|
|
|
} else if (op & P(OP, STORE)) {
|
|
/* store */
|
|
stats->store++;
|
|
|
|
if (!daddr) {
|
|
stats->st_noadrs++;
|
|
return -1;
|
|
}
|
|
|
|
if (lvl & P(LVL, HIT)) {
|
|
if (lvl & P(LVL, UNC)) stats->st_uncache++;
|
|
if (lvl & P(LVL, L1 )) stats->st_l1hit++;
|
|
}
|
|
if (lvl & P(LVL, MISS))
|
|
if (lvl & P(LVL, L1)) stats->st_l1miss++;
|
|
} else {
|
|
/* unparsable data_src? */
|
|
stats->noparse++;
|
|
return -1;
|
|
}
|
|
|
|
if (!mi->daddr.ms.map || !mi->iaddr.ms.map) {
|
|
stats->nomap++;
|
|
return -1;
|
|
}
|
|
|
|
#undef P
|
|
#undef HITM_INC
|
|
return err;
|
|
}
|
|
|
|
void c2c_add_stats(struct c2c_stats *stats, struct c2c_stats *add)
|
|
{
|
|
stats->nr_entries += add->nr_entries;
|
|
|
|
stats->locks += add->locks;
|
|
stats->store += add->store;
|
|
stats->st_uncache += add->st_uncache;
|
|
stats->st_noadrs += add->st_noadrs;
|
|
stats->st_l1hit += add->st_l1hit;
|
|
stats->st_l1miss += add->st_l1miss;
|
|
stats->load += add->load;
|
|
stats->ld_excl += add->ld_excl;
|
|
stats->ld_shared += add->ld_shared;
|
|
stats->ld_uncache += add->ld_uncache;
|
|
stats->ld_io += add->ld_io;
|
|
stats->ld_miss += add->ld_miss;
|
|
stats->ld_noadrs += add->ld_noadrs;
|
|
stats->ld_fbhit += add->ld_fbhit;
|
|
stats->ld_l1hit += add->ld_l1hit;
|
|
stats->ld_l2hit += add->ld_l2hit;
|
|
stats->ld_llchit += add->ld_llchit;
|
|
stats->lcl_hitm += add->lcl_hitm;
|
|
stats->rmt_hitm += add->rmt_hitm;
|
|
stats->tot_hitm += add->tot_hitm;
|
|
stats->rmt_hit += add->rmt_hit;
|
|
stats->lcl_dram += add->lcl_dram;
|
|
stats->rmt_dram += add->rmt_dram;
|
|
stats->nomap += add->nomap;
|
|
stats->noparse += add->noparse;
|
|
}
|