#include "util.h" #include "../perf.h" #include #include "evsel.h" #include "cgroup.h" #include "evlist.h" int nr_cgroups; static int cgroupfs_find_mountpoint(char *buf, size_t maxlen) { FILE *fp; char mountpoint[PATH_MAX + 1], tokens[PATH_MAX + 1], type[PATH_MAX + 1]; char *token, *saved_ptr = NULL; int found = 0; fp = fopen("/proc/mounts", "r"); if (!fp) return -1; /* * in order to handle split hierarchy, we need to scan /proc/mounts * and inspect every cgroupfs mount point to find one that has * perf_event subsystem */ while (fscanf(fp, "%*s %"STR(PATH_MAX)"s %"STR(PATH_MAX)"s %" STR(PATH_MAX)"s %*d %*d\n", mountpoint, type, tokens) == 3) { if (!strcmp(type, "cgroup")) { token = strtok_r(tokens, ",", &saved_ptr); while (token != NULL) { if (!strcmp(token, "perf_event")) { found = 1; break; } token = strtok_r(NULL, ",", &saved_ptr); } } if (found) break; } fclose(fp); if (!found) return -1; if (strlen(mountpoint) < maxlen) { strcpy(buf, mountpoint); return 0; } return -1; } static int open_cgroup(char *name) { char path[PATH_MAX + 1]; char mnt[PATH_MAX + 1]; int fd; if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1)) return -1; snprintf(path, PATH_MAX, "%s/%s", mnt, name); fd = open(path, O_RDONLY); if (fd == -1) fprintf(stderr, "no access to cgroup %s\n", path); return fd; } static int add_cgroup(struct perf_evlist *evlist, char *str) { struct perf_evsel *counter; struct cgroup_sel *cgrp = NULL; int n; /* * check if cgrp is already defined, if so we reuse it */ evlist__for_each_entry(evlist, counter) { cgrp = counter->cgrp; if (!cgrp) continue; if (!strcmp(cgrp->name, str)) break; cgrp = NULL; } if (!cgrp) { cgrp = zalloc(sizeof(*cgrp)); if (!cgrp) return -1; cgrp->name = str; cgrp->fd = open_cgroup(str); if (cgrp->fd == -1) { free(cgrp); return -1; } } /* * find corresponding event * if add cgroup N, then need to find event N */ n = 0; evlist__for_each_entry(evlist, counter) { if (n == nr_cgroups) goto found; n++; } if (atomic_read(&cgrp->refcnt) == 0) free(cgrp); return -1; found: atomic_inc(&cgrp->refcnt); counter->cgrp = cgrp; return 0; } void close_cgroup(struct cgroup_sel *cgrp) { if (cgrp && atomic_dec_and_test(&cgrp->refcnt)) { close(cgrp->fd); zfree(&cgrp->name); free(cgrp); } } int parse_cgroups(const struct option *opt __maybe_unused, const char *str, int unset __maybe_unused) { struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; const char *p, *e, *eos = str + strlen(str); char *s; int ret; if (list_empty(&evlist->entries)) { fprintf(stderr, "must define events before cgroups\n"); return -1; } for (;;) { p = strchr(str, ','); e = p ? p : eos; /* allow empty cgroups, i.e., skip */ if (e - str) { /* termination added */ s = strndup(str, e - str); if (!s) return -1; ret = add_cgroup(evlist, s); if (ret) { free(s); return -1; } } /* nr_cgroups is increased een for empty cgroups */ nr_cgroups++; if (!p) break; str = p+1; } return 0; } lue='4'>4space:mode:
authorSara Sharon <sara.sharon@intel.com>2016-11-30 16:49:11 +0200
committerLuca Coelho <luciano.coelho@intel.com>2017-02-03 16:26:42 +0200
commit4b70f07686d75d1eb5d956812cc810944e0b29b2 (patch)
tree49befb361c1a39ed29b7c499f4ca5f6e826e2ae5
parent5c228d63f963bd7e20b6a9b06e93272093e98628 (diff)
iwlwifi: mvm: synchronize firmware DMA paging memory
When driver needs to access the contents of a streaming DMA buffer without unmapping it it should call dma_sync_single_for_cpu(). Once the call has been made, the CPU "owns" the DMA buffer and can work with it as needed. Before the device accesses the buffer, however, ownership should be transferred back to it with dma_sync_single_for_device(). Both calls weren't performed by the driver, resulting with odd paging errors on some platforms. Fix it. Fixes: a6c4fb4441f4 ("iwlwifi: mvm: Add FW paging mechanism for the UMAC on PCI") Signed-off-by: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Diffstat