summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xlib/configure6
-rw-r--r--lib/mmio-ports.c19
2 files changed, 19 insertions, 6 deletions
diff --git a/lib/configure b/lib/configure
index eb4b9bf..57b064b 100755
--- a/lib/configure
+++ b/lib/configure
@@ -97,7 +97,7 @@ case $sys in
echo >>$c '#define PCI_HAVE_STDINT_H'
;;
freebsd*|kfreebsd*)
- echo_n " fbsd-device"
+ echo_n " fbsd-device mem-ports"
echo >>$c '#define PCI_HAVE_PM_FBSD_DEVICE'
echo >>$c '#define PCI_HAVE_PM_MMIO_CONF'
echo >>$c '#define PCI_PATH_FBSD_DEVICE "/dev/pci"'
@@ -107,7 +107,7 @@ case $sys in
fi
;;
openbsd)
- echo_n " obsd-device"
+ echo_n " obsd-device mem-ports"
echo >>$c '#define PCI_HAVE_PM_OBSD_DEVICE'
echo >>$c '#define PCI_HAVE_PM_MMIO_CONF'
echo >>$c '#define PCI_PATH_OBSD_DEVICE "/dev/pci"'
@@ -132,7 +132,7 @@ case $sys in
echo >>$m 'DIRINSTALL=mkdir -p'
;;
netbsd)
- echo_n " nbsd-libpci"
+ echo_n " nbsd-libpci mem-ports"
echo >>$c '#define PCI_HAVE_PM_NBSD_LIBPCI'
echo >>$c '#define PCI_HAVE_PM_MMIO_CONF'
echo >>$c '#define PCI_PATH_NBSD_DEVICE "/dev/pci0"'
diff --git a/lib/mmio-ports.c b/lib/mmio-ports.c
index b9e3926..ae9c30d 100644
--- a/lib/mmio-ports.c
+++ b/lib/mmio-ports.c
@@ -243,9 +243,9 @@ conf1_detect(struct pci_access *a)
return 0;
}
- if (access(devmem, R_OK))
+ if (access(devmem, R_OK | W_OK))
{
- a->debug("cannot access %s", devmem);
+ a->debug("cannot access %s: %s", devmem, strerror(errno));
return 0;
}
@@ -269,7 +269,7 @@ conf1_init(struct pci_access *a)
if (!validate_addrs(addrs))
a->error("Option mmio-conf1.addrs has invalid address format \"%s\".", addrs);
- a->fd = open(devmem, O_RDWR);
+ a->fd = open(devmem, O_RDWR | O_DSYNC); /* O_DSYNC bypass CPU cache for mmap() on Linux */
if (a->fd < 0)
a->error("Cannot open %s: %s.", devmem, strerror(errno));
}
@@ -316,6 +316,7 @@ conf1_read(struct pci_dev *d, int pos, byte *buf, int len)
return 0;
writel(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos & 0xfc), addr);
+ readl(addr); /* write barrier for address */
switch (len)
{
@@ -353,6 +354,7 @@ conf1_write(struct pci_dev *d, int pos, byte *buf, int len)
return 0;
writel(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos & 0xfc), addr);
+ readl(addr); /* write barrier for address */
switch (len)
{
@@ -367,6 +369,17 @@ conf1_write(struct pci_dev *d, int pos, byte *buf, int len)
break;
}
+ /*
+ * write barrier for data
+ * Note that we cannot read from data port because it may have side effect.
+ * Instead we read from address port (which should not have side effect) to
+ * create a barrier between two conf1_write() calls. But this does not have
+ * to be 100% correct as it does not ensure barrier on data port itself.
+ * Correct way is to issue CPU instruction for full hw sync barrier but gcc
+ * does not provide any (builtin) function yet.
+ */
+ readl(addr);
+
return 1;
}