diff options
author | Jesse Barnes <jbarnes@hobbes.(none)> | 2008-06-23 11:24:04 -0700 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-06-23 11:24:04 -0700 |
commit | 7282b53c47c2435c1ea23948272c9ccf1798178a (patch) | |
tree | ff2841dd47f0c29f8078c85cd356441cd478d110 | |
parent | f49f66710b6c3cc5edfd0681cf7b69063cb4b893 (diff) |
Support write combine resource files in Linux sysfs
Starting with version 2.6.26, Linux will support resourceN_wc files which
export write combining mappings of PCI resource ranges, so support them if
present in libpciaccess.
-rw-r--r-- | src/linux_sysfs.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/src/linux_sysfs.c b/src/linux_sysfs.c index 3cbed76..ca4d3ef 100644 --- a/src/linux_sysfs.c +++ b/src/linux_sysfs.c @@ -484,6 +484,40 @@ pci_device_linux_sysfs_write( struct pci_device * dev, const void * data, return err; } +static int +pci_device_linux_sysfs_map_range_wc(struct pci_device *dev, + struct pci_device_mapping *map) +{ + char name[256]; + int fd; + const int prot = ((map->flags & PCI_DEV_MAP_FLAG_WRITABLE) != 0) + ? (PROT_READ | PROT_WRITE) : PROT_READ; + const int open_flags = ((map->flags & PCI_DEV_MAP_FLAG_WRITABLE) != 0) + ? O_RDWR : O_RDONLY; + const off_t offset = map->base - dev->regions[map->region].base_addr; + + snprintf(name, 255, "%s/%04x:%02x:%02x.%1u/resource%u_wc", + SYS_BUS_PCI, + dev->domain, + dev->bus, + dev->dev, + dev->func, + map->region); + fd = open(name, open_flags); + if (fd == -1) + return errno; + + map->memory = mmap(NULL, map->size, prot, MAP_SHARED, fd, offset); + if (map->memory == MAP_FAILED) { + map->memory = NULL; + close(fd); + return errno; + } + + close(fd); + + return 0; +} /** * Map a memory region for a device using the Linux sysfs interface. @@ -521,6 +555,11 @@ pci_device_linux_sysfs_map_range(struct pci_device *dev, }; #endif + /* For WC mappings, try sysfs resourceN_wc file first */ + if ((map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE) && + !pci_device_linux_sysfs_map_range_wc(dev, map)) + return 0; + snprintf(name, 255, "%s/%04x:%02x:%02x.%1u/resource%u", SYS_BUS_PCI, dev->domain, |