Support write combine resource files in Linux sysfs
authorJesse Barnes <jbarnes@hobbes.(none)>
Mon, 23 Jun 2008 18:24:04 +0000 (11:24 -0700)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Mon, 23 Jun 2008 18:24:04 +0000 (11:24 -0700)
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.

src/linux_sysfs.c

index 3cbed76..ca4d3ef 100644 (file)
@@ -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,