summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@hobbes.(none)>2008-06-23 11:24:04 -0700
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-06-23 11:24:04 -0700
commit7282b53c47c2435c1ea23948272c9ccf1798178a (patch)
treeff2841dd47f0c29f8078c85cd356441cd478d110
parentf49f66710b6c3cc5edfd0681cf7b69063cb4b893 (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.c39
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,