Commit 16ce4678 authored by Patryk Wlazlyn's avatar Patryk Wlazlyn Committed by Len Brown
Browse files

tools/power turbostat: Allow mapping multiple PMT files with the same GUID



Some platforms may expose multiple telemetry files identified with the
same GUID. Interpreting it correctly, to associate given counter with a
CPU, core or a package requires more metadata from the user.

Parse and create  ordered, linked list of those PMT aggregators, so that
we can identify specific aggregator with GUID + sequence number.

Signed-off-by: default avatarPatryk Wlazlyn <patryk.wlazlyn@linux.intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 4265a865
Loading
Loading
Loading
Loading
+40 −35
Original line number Diff line number Diff line
@@ -9033,46 +9033,35 @@ int parse_telem_info_file(int fd_dir, const char *info_filename, const char *for

struct pmt_mmio *pmt_mmio_open(unsigned int target_guid)
{
	DIR *dirp;
	struct dirent *entry;
	struct pmt_diriter_t pmt_iter;
	const struct dirent *entry;
	struct stat st;
	unsigned int telem_idx;
	int fd_telem_dir, fd_pmt;
	unsigned long guid, size, offset;
	size_t mmap_size;
	void *mmio;
	struct pmt_mmio *ret = NULL;
	struct pmt_mmio *head = NULL, *last = NULL;
	struct pmt_mmio *new_pmt = NULL;

	if (stat(SYSFS_TELEM_PATH, &st) == -1)
		return NULL;

	dirp = opendir(SYSFS_TELEM_PATH);
	if (dirp == NULL)
	pmt_diriter_init(&pmt_iter);
	entry = pmt_diriter_begin(&pmt_iter, SYSFS_TELEM_PATH);
	if (!entry) {
		pmt_diriter_remove(&pmt_iter);
		return NULL;
	}

	for (;;) {
		entry = readdir(dirp);

		if (entry == NULL)
			break;

		if (strcmp(entry->d_name, ".") == 0)
			continue;

		if (strcmp(entry->d_name, "..") == 0)
			continue;

		if (sscanf(entry->d_name, "telem%u", &telem_idx) != 1)
			continue;

		if (fstatat(dirfd(dirp), entry->d_name, &st, 0) == -1) {
	for (;entry != NULL; entry = pmt_diriter_next(&pmt_iter)) {
		if (fstatat(dirfd(pmt_iter.dir), entry->d_name, &st, 0) == -1) {
			break;
		}

		if (!S_ISDIR(st.st_mode))
			continue;

		fd_telem_dir = openat(dirfd(dirp), entry->d_name, O_RDONLY);
		fd_telem_dir = openat(dirfd(pmt_iter.dir), entry->d_name, O_RDONLY);
		if (fd_telem_dir == -1) {
			break;
		}
@@ -9106,35 +9095,51 @@ struct pmt_mmio *pmt_mmio_open(unsigned int target_guid)
		mmap_size = ROUND_UP_TO_PAGE_SIZE(size);
		mmio = mmap(0, mmap_size, PROT_READ, MAP_SHARED, fd_pmt, 0);
		if (mmio != MAP_FAILED) {

			if (debug)
				fprintf(stderr, "%s: 0x%lx mmaped at: %p\n", __func__, guid, mmio);

			ret = calloc(1, sizeof(*ret));
			new_pmt = calloc(1, sizeof(*new_pmt));

			if (!ret) {
			if (!new_pmt) {
				fprintf(stderr, "%s: Failed to allocate pmt_mmio\n", __func__);
				exit(1);
			}

			ret->guid = guid;
			ret->mmio_base = mmio;
			ret->pmt_offset = offset;
			ret->size = size;
			/*
			 * Create linked list of mmaped regions,
			 * but preserve the ordering from sysfs.
			 * Ordering is important for the user to
			 * use the seq=%u parameter when adding a counter.
			 */
			new_pmt->guid = guid;
			new_pmt->mmio_base = mmio;
			new_pmt->pmt_offset = offset;
			new_pmt->size = size;
			new_pmt->next = pmt_mmios;

			if (last)
				last->next = new_pmt;
			else
				head = new_pmt;

			ret->next = pmt_mmios;
			pmt_mmios = ret;
			last = new_pmt;
		}

loop_cleanup_and_break:
		close(fd_pmt);
		close(fd_telem_dir);
		break;
	}

	closedir(dirp);
	pmt_diriter_remove(&pmt_iter);

	return ret;
	/*
	 * If we found something, stick just
	 * created linked list to the front.
	 */
	if (head)
		pmt_mmios = head;

	return head;
}

struct pmt_mmio *pmt_mmio_find(unsigned int guid)