Author: jhb
Date: Thu Jun 27 20:35:39 2013
New Revision: 252317
URL: http://svnweb.freebsd.org/changeset/base/252317

Log:
  MFC 250418,252166:
  Revision 233677 broke certain machines.  Specifically, if the firmware/BIOS
  assigned conflicting ranges to BARs then leaving the BARs alone could
  result in one device stealing mmio accesses intended to go to a second
  device.  Prior to 233677 the PCI bus driver attempted to handle this case
  by clearing the BAR to 0 depending on BARs based at 0 not decoding (which
  is not guaranteed to be true).  Now when a conflicting BAR is detected the
  following steps are taken:
  
   1) If hw.pci.realloc_bars (a new tunable) is enabled (default is disabled),
      then ignore the current BAR setting from the firmware and attempt to
      allocate a fresh resource range for the BAR.
  
   2) If 1) failed (or was disabled), disable decoding for the relevant
      BAR type (e.g. disable mem decoding for a memory BAR) and emit a
      warning if booting verbose.

Modified:
  stable/9/sys/dev/pci/pci.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)

Modified: stable/9/sys/dev/pci/pci.c
==============================================================================
--- stable/9/sys/dev/pci/pci.c  Thu Jun 27 20:27:34 2013        (r252316)
+++ stable/9/sys/dev/pci/pci.c  Thu Jun 27 20:35:39 2013        (r252317)
@@ -289,6 +289,12 @@ SYSCTL_INT(_hw_pci, OID_AUTO, enable_io_
 enable these bits correctly.  We'd like to do this all the time, but there\n\
 are some peripherals that this causes problems with.");
 
+static int pci_do_realloc_bars = 0;
+TUNABLE_INT("hw.pci.realloc_bars", &pci_do_realloc_bars);
+SYSCTL_INT(_hw_pci, OID_AUTO, realloc_bars, CTLFLAG_RW,
+    &pci_do_realloc_bars, 0,
+    "Attempt to allocate a new range for any BARs whose original 
firmware-assigned ranges fail to allocate during the initial device scan.");
+
 static int pci_do_power_nodriver = 0;
 TUNABLE_INT("hw.pci.do_power_nodriver", &pci_do_power_nodriver);
 SYSCTL_INT(_hw_pci, OID_AUTO, do_power_nodriver, CTLFLAG_RW,
@@ -2745,13 +2751,34 @@ pci_add_map(device_t bus, device_t dev, 
         */
        res = resource_list_reserve(rl, bus, dev, type, &reg, start, end, count,
            prefetch ? RF_PREFETCHABLE : 0);
+       if (pci_do_realloc_bars && res == NULL && (start != 0 || end != ~0ul)) {
+               /*
+                * If the allocation fails, try to allocate a resource for
+                * this BAR using any available range.  The firmware felt
+                * it was important enough to assign a resource, so don't
+                * disable decoding if we can help it.
+                */
+               resource_list_delete(rl, type, reg);
+               resource_list_add(rl, type, reg, 0, ~0ul, count);
+               res = resource_list_reserve(rl, bus, dev, type, &reg, 0, ~0ul,
+                   count, prefetch ? RF_PREFETCHABLE : 0);
+       }
        if (res == NULL) {
                /*
                 * If the allocation fails, delete the resource list entry
-                * to force pci_alloc_resource() to allocate resources
-                * from the parent.
+                * and disable decoding for this device.
+                *
+                * If the driver requests this resource in the future,
+                * pci_reserve_map() will try to allocate a fresh
+                * resource range.
                 */
                resource_list_delete(rl, type, reg);
+               pci_disable_io(dev, type);
+               if (bootverbose)
+                       device_printf(bus,
+                           "pci%d:%d:%d:%d bar %#x failed to allocate\n",
+                           pci_get_domain(dev), pci_get_bus(dev),
+                           pci_get_slot(dev), pci_get_function(dev), reg);
        } else {
                start = rman_get_start(res);
                pci_write_bar(dev, pm, start);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to