summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu.herrb@laas.fr>2008-08-09 12:14:30 +0200
committerMatthieu Herrb <matthieu@bluenote.herrb.net>2008-08-09 12:14:30 +0200
commit81e2ee60b8bab0b8046acfa95b95f56ddc5d943a (patch)
tree8858903e315a7ff8d6969b69c5eec5be3dc80b2e
parent15b27bc2d50aa6fb4b129fe1ebc10a865804d828 (diff)
parent45015ab30b36bdaefd3f3aeab73d287023928826 (diff)
Merge branch 'master' into obsd
-rw-r--r--configure.ac15
-rw-r--r--src/Makefile.am2
-rw-r--r--src/common_device_name.c39
-rw-r--r--src/freebsd_pci.c1
-rw-r--r--src/linux_sysfs.c64
5 files changed, 104 insertions, 17 deletions
diff --git a/configure.ac b/configure.ac
index ed81dc4..67b18f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -40,7 +40,7 @@ dnl refers to ${prefix}. Thus we have to use `eval' twice.
AC_PREREQ([2.57])
-AC_INIT(libpciaccess, 0.10.1, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=libpciaccess], libpciaccess)
+AC_INIT(libpciaccess, 0.10.3, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=libpciaccess], libpciaccess)
AM_INIT_AUTOMAKE([dist-bzip2])
AM_MAINTAINER_MODE
@@ -59,6 +59,19 @@ AC_ARG_WITH(pciids-path,
[PCIIDS_PATH="$DEFAULT_PCIIDS_PATH"])
AC_DEFINE_DIR(PCIIDS_PATH, PCIIDS_PATH, [Path to pci.ids])
+AC_ARG_WITH(zlib,
+ AS_HELP_STRING([--with-zlib], [Enable zlib support to read gzip compressed pci.ids]),
+ [use_zlib="yes"],
+ [use_zlib="no"])
+if test "x$use_zlib" = xyes; then
+ AC_CHECK_LIB(z, gzopen,
+ [PCIACCESS_LIBS="$PCIACCESS_LIBS -lz"],
+ [AC_MSG_ERROR(Check for zlib library failed)])
+ AC_CHECK_HEADER([zlib.h],
+ [AC_DEFINE(HAVE_ZLIB, 1, [Use zlib to read gzip compressed pci.ids])],
+ [AC_MSG_ERROR(Check for zlib.h header file failed)])
+fi
+
if test "x$GCC" = "xyes"; then
GCC_WARNINGS1="-Wall -Wpointer-arith -Wstrict-prototypes"
GCC_WARNINGS2="-Wmissing-prototypes -Wmissing-declarations"
diff --git a/src/Makefile.am b/src/Makefile.am
index 8bec117..8c53de5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -55,7 +55,7 @@ INCLUDES = -I$(top_srcdir)/include
libpciaccess_la_LIBADD = @PCIACCESS_LIBS@
-libpciaccess_la_LDFLAGS = -version-number 0:10:1 -no-undefined
+libpciaccess_la_LDFLAGS = -version-number 0:10:2 -no-undefined
libpciaccessincludedir = $(includedir)
libpciaccessinclude_HEADERS = \
diff --git a/src/common_device_name.c b/src/common_device_name.c
index b105187..877f218 100644
--- a/src/common_device_name.c
+++ b/src/common_device_name.c
@@ -50,6 +50,31 @@
#define DO_MATCH(a,b) (((a) == PCI_MATCH_ANY) || ((a) == (b)))
+#ifdef HAVE_ZLIB
+#include <zlib.h>
+typedef gzFile pci_id_file;
+
+static pci_id_file
+pci_id_file_open()
+{
+ pci_id_file result;
+
+ result = gzopen(PCIIDS_PATH "/pci.ids.gz", "rb");
+ if (result)
+ return result;
+
+ return gzopen(PCIIDS_PATH "/pci.ids", "rb");
+}
+
+#define pci_id_file_gets(l, s, f) gzgets(f, l, s)
+#define pci_id_file_close(f) gzclose(f)
+#else
+typedef FILE pci_id_file;
+#define pci_id_file_open() fopen(PCIIDS_PATH "/pci.ids", "r")
+#define pci_id_file_gets(l, s, f) fgets(l, s, f)
+#define pci_id_file_close(f) fclose(f)
+#endif
+
/**
* Node for sorting vendor IDs.
*
@@ -96,12 +121,6 @@ struct pci_device_leaf {
_pci_hidden struct pci_id_node * tree = NULL;
/**
- * Name of the file containing the PCI ID information.
- */
-static const char pci_id_file[] = PCIIDS_PATH "/pci.ids";
-
-
-/**
* Get a pointer to the leaf node for a vendor ID.
*
* If the vendor ID does not exist in the tree, it is added.
@@ -170,7 +189,7 @@ insert( uint16_t vendor )
static void
populate_vendor( struct pci_id_leaf * vend, int fill_device_data )
{
- FILE * f = fopen( pci_id_file, "r" );
+ pci_id_file * f = pci_id_file_open();
char buf[128];
unsigned vendor = PCI_MATCH_ANY;
@@ -186,12 +205,12 @@ populate_vendor( struct pci_id_leaf * vend, int fill_device_data )
* anything. This avoids wasted processing and potential memory leaks.
*/
if (vend->num_devices != 0) {
- fclose(f);
+ pci_id_file_close( f );
return;
}
- while( fgets( buf, sizeof( buf ), f ) != NULL ) {
+ while( pci_id_file_gets( buf, sizeof( buf ), f ) != NULL ) {
unsigned num_tabs;
char * new_line;
size_t length;
@@ -284,7 +303,7 @@ populate_vendor( struct pci_id_leaf * vend, int fill_device_data )
}
}
- fclose( f );
+ pci_id_file_close( f );
}
diff --git a/src/freebsd_pci.c b/src/freebsd_pci.c
index 67ca9e3..4b8f7ba 100644
--- a/src/freebsd_pci.c
+++ b/src/freebsd_pci.c
@@ -64,6 +64,7 @@
*
* It is initialized once and used as a global, just as pci_system is used.
*/
+_pci_hidden
struct freebsd_pci_system {
/* This must be the first entry in the structure, as pci_system_cleanup()
* frees pci_sys.
diff --git a/src/linux_sysfs.c b/src/linux_sysfs.c
index 9e53fac..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,
@@ -537,12 +576,11 @@ pci_device_linux_sysfs_map_range(struct pci_device *dev,
map->memory = mmap(NULL, map->size, prot, MAP_SHARED, fd, offset);
if (map->memory == MAP_FAILED) {
- err = errno;
map->memory = NULL;
+ close(fd);
+ return errno;
}
- close(fd);
-
#ifdef HAVE_MTRR
if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) != 0) {
sentry.type = MTRR_TYPE_WRBACK;
@@ -562,11 +600,27 @@ pci_device_linux_sysfs_map_range(struct pci_device *dev,
}
/* KLUDGE ALERT -- rewrite the PTEs to turn off the CD and WT bits */
mprotect (map->memory, map->size, PROT_NONE);
- mprotect (map->memory, map->size, PROT_READ|PROT_WRITE);
+ err = mprotect (map->memory, map->size, PROT_READ|PROT_WRITE);
+
+ if (err != 0) {
+ fprintf(stderr, "mprotect(PROT_READ | PROT_WRITE) failed: %s\n",
+ strerror(errno));
+ fprintf(stderr, "remapping without mprotect performance kludge.\n");
+
+ munmap(map->memory, map->size);
+ map->memory = mmap(NULL, map->size, prot, MAP_SHARED, fd, offset);
+ if (map->memory == MAP_FAILED) {
+ map->memory = NULL;
+ close(fd);
+ return errno;
+ }
+ }
}
#endif
- return err;
+ close(fd);
+
+ return 0;
}
/**