Example #1
0
unsigned int init_pci(unsigned char bus, const unsigned char forcemem) {

	int ret = pci_system_init();
	if (ret)
		die(_("Failed to init pciaccess"));

	struct pci_id_match match;

	match.vendor_id = 0x1002;
	match.device_id = PCI_MATCH_ANY;
	match.subvendor_id = PCI_MATCH_ANY;
	match.subdevice_id = PCI_MATCH_ANY;
	match.device_class = 0;
	match.device_class_mask = 0;
	match.match_data = 0;

	struct pci_device_iterator *iter = pci_id_match_iterator_create(&match);
	struct pci_device *dev = NULL;
	char busid[32];

	while ((dev = pci_device_next(iter))) {
		pci_device_probe(dev);
		if ((dev->device_class & 0x00ffff00) != 0x00030000 &&
			(dev->device_class & 0x00ffff00) != 0x00038000)
			continue;
		snprintf(busid, sizeof(busid), "pci:%04x:%02x:%02x.%u",
				dev->domain, dev->bus, dev->dev, dev->func);
		if (!bus || bus == dev->bus)
			break;
	}

	pci_iterator_destroy(iter);

	if (!dev)
		die(_("Can't find Radeon cards"));

	const unsigned int device_id = dev->device_id;
	int reg = 2;
	if (getfamily(device_id) >= BONAIRE)
		reg = 5;

	if (!dev->regions[reg].size) die(_("Can't get the register area size"));

//	printf("Found area %p, size %lu\n", area, dev->regions[reg].size);

	// DRM support for VRAM
	drm_fd = drmOpen(NULL, busid);
	if (drm_fd >= 0) {
		drmVersionPtr ver = drmGetVersion(drm_fd);
		if (strcmp(ver->name, "radeon") != 0 && strcmp(ver->name, "amdgpu") != 0) {
			close(drm_fd);
			drm_fd = -1;
		}
		strcpy(drm_name, ver->name);
		drmFreeVersion(ver);
	}
	if (drm_fd < 0 && access("/dev/ati/card0", F_OK) == 0) // fglrx path
		drm_fd = open("/dev/ati/card0", O_RDWR);

	use_ioctl = 0;
	if (drm_fd >= 0) {
		authenticate_drm(drm_fd);
		uint32_t rreg = 0x8010;
		use_ioctl = get_drm_value(drm_fd, RADEON_INFO_READ_REG, &rreg);
	}

	if (forcemem) {
		printf(_("Forcing the /dev/mem path.\n"));
		use_ioctl = 0;
	}

	if (!use_ioctl) {
		int mem = open("/dev/mem", O_RDONLY);
		if (mem < 0) die(_("Cannot access GPU registers, are you root?"));

		area = mmap(NULL, MMAP_SIZE, PROT_READ, MAP_PRIVATE, mem,
				dev->regions[reg].base_addr + 0x8000);
		if (area == MAP_FAILED) die(_("mmap failed"));
	}

	bits.vram = 0;
	if (drm_fd < 0) {
		printf(_("Failed to open DRM node, no VRAM support.\n"));
	} else {
		drmDropMaster(drm_fd);
		drmVersionPtr ver = drmGetVersion(drm_fd);

/*		printf("Version %u.%u.%u, name %s\n",
			ver->version_major,
			ver->version_minor,
			ver->version_patchlevel,
			ver->name);*/

		if (ver->version_major < 2 ||
			(ver->version_major == 2 && ver->version_minor < 36)) {
			printf(_("Kernel too old for VRAM reporting.\n"));
			drmFreeVersion(ver);
			goto out;
		}
		drmFreeVersion(ver);

		// No version indicator, so we need to test once
		// We use different codepaths for radeon and amdgpu
		// We store vram_size and check below if the ret value is sane
		if (strcmp(drm_name, "radeon") == 0) {
			struct drm_radeon_gem_info gem;

			ret = drmCommandWriteRead(drm_fd, DRM_RADEON_GEM_INFO,
							&gem, sizeof(gem));
			vramsize = gem.vram_size;
		} else if (strcmp(drm_name, "amdgpu") == 0) {
#ifdef ENABLE_AMDGPU
			struct drm_amdgpu_info_vram_gtt vram_gtt = {};

			struct drm_amdgpu_info request;
			memset(&request, 0, sizeof(request));
			request.return_pointer = (unsigned long) &vram_gtt;
			request.return_size = sizeof(vram_gtt);
			request.query = AMDGPU_INFO_VRAM_GTT;

			ret = drmCommandWrite(drm_fd, DRM_AMDGPU_INFO,
						&request, sizeof(request));
			vramsize = vram_gtt.vram_size;
#else
			printf(_("amdgpu DRM driver is used, but amdgpu VRAM size reporting is not enabled\n"));
#endif
		}
		if (ret) {
			printf(_("Failed to get VRAM size, error %d\n"),
				ret);
			goto out;
		}

		ret = getvram();
		if (ret == 0) {
			if (strcmp(drm_name, "amdgpu") == 0) {
#ifndef ENABLE_AMDGPU
				printf(_("amdgpu DRM driver is used, but amdgpu VRAM usage reporting is not enabled\n"));
#endif
			}
			printf(_("Failed to get VRAM usage, kernel likely too old\n"));
			goto out;
		}

		bits.vram = 1;
	}

	out:

	pci_system_cleanup();

	return device_id;
}
Example #2
0
static void *collector(void *arg) {
	struct collector_args_t *args = (struct collector_args_t *) arg;

	const unsigned int ticks = args->ticks;
	const unsigned int dumpinterval = args->dumpinterval;

	struct bits_t res[2];

	// Save one second's worth of history
	struct bits_t *history = calloc(ticks * dumpinterval, sizeof(struct bits_t));
	unsigned int cur = 0, curres = 0;

	const useconds_t sleeptime = 1e6 / ticks;

	while (1) {
		unsigned int stat = readgrbm();

		memset(&history[cur], 0, sizeof(struct bits_t));

		if (stat & bits.ee) history[cur].ee = 1;
		if (stat & bits.vgt) history[cur].vgt = 1;
		if (stat & bits.gui) history[cur].gui = 1;
		if (stat & bits.ta) history[cur].ta = 1;
		if (stat & bits.tc) history[cur].tc = 1;
		if (stat & bits.sx) history[cur].sx = 1;
		if (stat & bits.sh) history[cur].sh = 1;
		if (stat & bits.spi) history[cur].spi = 1;
		if (stat & bits.smx) history[cur].smx = 1;
		if (stat & bits.sc) history[cur].sc = 1;
		if (stat & bits.pa) history[cur].pa = 1;
		if (stat & bits.db) history[cur].db = 1;
		if (stat & bits.cr) history[cur].cr = 1;
		if (stat & bits.cb) history[cur].cb = 1;
		history[cur].mclk = getmclk();
		history[cur].sclk = getsclk();

		usleep(sleeptime);
		cur++;
		cur %= ticks * dumpinterval;

		// One second has passed, we have one sec's worth of data
		if (cur == 0) {
			unsigned int i;

			memset(&res[curres], 0, sizeof(struct bits_t));

			for (i = 0; i < ticks * dumpinterval; i++) {
				res[curres].ee += history[i].ee;
				res[curres].vgt += history[i].vgt;
				res[curres].gui += history[i].gui;
				res[curres].ta += history[i].ta;
				res[curres].tc += history[i].tc;
				res[curres].sx += history[i].sx;
				res[curres].sh += history[i].sh;
				res[curres].spi += history[i].spi;
				res[curres].smx += history[i].smx;
				res[curres].sc += history[i].sc;
				res[curres].pa += history[i].pa;
				res[curres].db += history[i].db;
				res[curres].cb += history[i].cb;
				res[curres].cr += history[i].cr;
				res[curres].mclk += history[i].mclk;
				res[curres].sclk += history[i].sclk;
			}

			res[curres].vram = getvram();
			res[curres].gtt = getgtt();

			// Atomically write it to the pointer
			__sync_bool_compare_and_swap(&results, results, &res[curres]);

			curres++;
			curres %= 2;
		}
	}

	return NULL;
}