[PATCH] support resourceN_wc files in libpciaccess

Jesse Barnes jbarnes at virtuousgeek.org
Sat Jun 14 13:06:33 PDT 2008


I'm about to push a patch to the kernel which will add resourceN_wc files to 
the sysfs PCI API.  To support the new interface in X, I added this patch to 
libpciaccess; if it looks ok I'll go ahead and push it (works here for me so 
far).  Given all the other stuff we do in this routine now, refactoring it 
into sysfs, mmap and mtrr functions might be a good idea, but adding a new 
function is also pretty clean.

Thanks,
Jesse

diff --git a/src/linux_sysfs.c b/src/linux_sysfs.c
index b1d196c..0cc6741 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,





More information about the xorg mailing list