[igt-dev] [PATCH i-g-t] lib: add pci helper functions to intel_chipset

Jani Nikula jani.nikula at linux.intel.com
Tue Mar 12 13:43:57 UTC 2019


On Mon, 11 Mar 2019, Daniel Mrzyglod <daniel.t.mrzyglod at intel.com> wrote:
> From: "Mrzyglod, Daniel T" <daniel.t.mrzyglod at intel.com>
>
> This patch add two helper functions:
>  * reading register from PCI based on open fd
>  * getting PCI domain/bus/dev/func based on fd
>
> The reason why we need this function is up to scenario when we have
> multiple PCI devices.
>
> Signed-off-by: Mrzyglod, Daniel T <daniel.t.mrzyglod at intel.com>
> ---
>  lib/intel_chipset.c | 176 ++++++++++++++++++++++++++++++++++++++++++++
>  lib/intel_chipset.h |  13 ++++
>  2 files changed, 189 insertions(+)
>
> diff --git a/lib/intel_chipset.c b/lib/intel_chipset.c
> index 4748a3fb..3dd722d6 100644
> --- a/lib/intel_chipset.c
> +++ b/lib/intel_chipset.c
> @@ -36,6 +36,7 @@
>  #include <fcntl.h>
>  #include <sys/stat.h>
>  #include <sys/mman.h>
> +#include <linux/limits.h>
>  #include "i915_drm.h"
>  
>  #include "drmtest.h"
> @@ -178,3 +179,178 @@ intel_check_pch(void)
>  		return;
>  	}
>  }
> +
> +/**
> + * parse_pci_address_string:
> + * @pci_address: PCI string in form 0000:00:00.0
> + * @dev_addr: structure to be filled by this parsing function
> + *
> + * This function fill fd_pci_address structure with data about pci: domain, bus
> + * device, function
> + * Return:
> + * O or -EINVAL
> + */
> +static int parse_pci_address_string(char *pci_address,
> +				    struct fd_pci_address *dev_addr)
> +{
> +	unsigned long val;
> +	char *pch;
> +	int i = 0;
> +
> +	if (strlen(pci_address) != 12)
> +		return -EINVAL;
> +
> +	/* parse PCI address  string for domain */
> +	pch = strtok(pci_address, ":.");
> +	errno = 0;
> +	val = strtoul(pch, NULL, 16);
> +	if (errno != 0 || val > UINT16_MAX)
> +		return -EINVAL;
> +	dev_addr->domain = val;
> +
> +	/* parse  PCI address for: BUS DEVICE FUNCTION */
> +	for (i = 0; i < 3; i++) {
> +		pch = strtok(NULL, ":.");
> +		errno = 0;
> +		val = strtoul(pch, NULL, 16);
> +		if (errno != 0 || val > UINT8_MAX)
> +			return -EINVAL;
> +
> +		switch (i) {
> +		case 0:
> +			dev_addr->bus = val;
> +			break;
> +		case 1:
> +			dev_addr->dev = val;
> +			break;
> +		case 2:
> +			dev_addr->func = val;
> +			break;
> +		default:
> +			return -EINVAL;
> +		break;
> +		}
> +	}
> +
> +	pch = strtok(NULL, ":.");
> +	if (pch)
> +		return -EINVAL;
> +
> +	return 0;
> +}

static int parse_pci_address_string(const char *pci_address,
				    struct fd_pci_address *dev_addr)
{
        int ret;
	unsigned int domain, bus, dev, func;

	ret = sscanf(pci_address, "%4x:%2x:%2x.%1x", &domain, &bus, &dev, &func);
	if (ret != 4)
        	return -EINVAL;

	dev_addr->domain = domain;
	dev_addr->bus = bus;
        dev_addr->dev = dev;
        dev_addr->func = func;

	return 0;
}

BR,
Jani.


> +
> +/**
> + * parse_pci_filepath_string:
> + * @filepath: string in form ../../devices/pci0000:00/0000:00:00.0/drm/card0
> + * @dev_addr: structure to be filled by this parsing function
> + *
> + * This function parse filepath string to PCI address string 0000:00:00.0 form.
> + * and fill dev_addr.
> + * Return:
> + * O or -EINVAL
> + */
> +static int
> +parse_pci_filepath_string(char *filepath, struct fd_pci_address *dev_addr)
> +{
> +	char *pch = strstr(filepath, "pci");
> +	char *begin = NULL;
> +	char *end = NULL;
> +
> +	if (pch) {
> +		pch = strstr(pch, "/");
> +		pch++;
> +		begin = pch;
> +		end = strstr(pch, "/");
> +		*end = '\0';
> +		} else {
> +			return -EINVAL;
> +		}
> +	if (strlen(begin) != 12)
> +		return -EINVAL;
> +	if (parse_pci_address_string(begin, dev_addr) < 0)
> +		return -EINVAL;
> +	return 0;
> +}
> +
> +/**
> + * get_pci_address_space:
> + * @fd: file descriptor of opened device
> + * @dev_addr: structure with pci_address to be filled by this parsing function
> + *
> + * This function fill dev_addr from reading fstats from opened device.
> + * from it.
> + * Return:
> + * O or -EINVAL
> + */
> +int intel_get_pci_address_space(int fd, struct fd_pci_address *dev_addr)
> +{
> +	struct stat sb;
> +	char filepath[PATH_MAX];
> +	char fdp[PATH_MAX];
> +	int ret = -1;
> +
> +	if (fstat(fd, &sb) == -1) {
> +		perror("stat");
> +		return -EINVAL;
> +	}
> +
> +	sprintf(fdp, "/sys/dev/char/%d:%d",  major(sb.st_rdev),
> +		minor(sb.st_rdev));
> +	readlink(fdp, filepath, PATH_MAX);
> +
> +	ret = parse_pci_filepath_string(filepath, dev_addr);
> +	if (ret < 0)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +/**
> + * pci_read_register_u32:
> + * @fd: file descriptor of opened device
> + * @reg_name: offset in mmio space
> + *
> + * This function read UINT32 from pci.
> + * Return:
> + * Register value or igt_fail
> + */
> +uint32_t intel_pci_read_register_u32(int fd, uint32_t reg_name)
> +{
> +	uint32_t reg_val = 0;
> +	int error = -1;
> +	int mmio_bar, mmio_size;
> +	struct pci_device *dev;
> +	struct fd_pci_address dev_addr;
> +	void *igt_mmio;
> +
> +	intel_get_pci_address_space(fd, &dev_addr);
> +	pci_system_init();
> +	dev = pci_device_find_by_slot((uint32_t)dev_addr.domain,
> +				      (uint32_t)dev_addr.bus,
> +				      (uint32_t)dev_addr.dev,
> +				      (uint32_t)dev_addr.func);
> +
> +	error = pci_device_probe(dev);
> +	igt_fail_on_f(error != 0,
> +		      "Couldn't probe graphics card\n");
> +
> +	mmio_bar = 0;
> +	mmio_size = 2 * 1024 * 1024;
> +
> +	error = pci_device_map_range(dev,
> +				     dev->regions[mmio_bar].base_addr,
> +				     mmio_size,
> +				     PCI_DEV_MAP_FLAG_WRITABLE,
> +				     &igt_mmio);
> +	igt_fail_on_f(error != 0,
> +		      "Couldn't map MMIO region\n");
> +
> +	reg_val = *(volatile uint32_t *)((volatile char *)igt_mmio + reg_name);
> +
> +	error = pci_device_unmap_range(dev, igt_mmio,
> +				       mmio_size);
> +	igt_fail_on_f(error != 0,
> +		      "Couldn't unmap MMIO region\n");
> +
> +	return reg_val;
> +}
> diff --git a/lib/intel_chipset.h b/lib/intel_chipset.h
> index 40170b7b..96a618eb 100644
> --- a/lib/intel_chipset.h
> +++ b/lib/intel_chipset.h
> @@ -73,6 +73,19 @@ struct intel_device_info {
>  
>  const struct intel_device_info *intel_get_device_info(uint16_t devid) __attribute__((pure));
>  
> +struct fd_pci_address {
> +	/**
> +	 * PCI Address
> +	 */
> +	uint16_t	domain;
> +	uint8_t		bus;
> +	uint8_t		dev;
> +	uint8_t		func;
> +};
> +
> +uint32_t intel_pci_read_register_u32(int fd, uint32_t reg_name);
> +int intel_get_pci_address_space(int fd, struct fd_pci_address *dev_addr);
> +
>  unsigned intel_gen(uint16_t devid) __attribute__((pure));
>  unsigned intel_gt(uint16_t devid) __attribute__((pure));

-- 
Jani Nikula, Intel Open Source Graphics Center


More information about the igt-dev mailing list