pcib allocation failure

John Baldwin jhb at freebsd.org
Mon Jun 6 14:52:34 UTC 2011


On Saturday, May 28, 2011 9:45:48 pm deeptech71 at gmail.com wrote:
> On Thu, May 26, 2011 at 3:40 PM, John Baldwin <jhb at freebsd.org> wrote:
> > Ohh, you have two devices behind this bridge that have prefetch ranges.
> >
> > As a hack, can you try this:
> >
> > Index: pci_pci.c
> > ===================================================================
> > --- pci_pci.c   (revision 222285)
> > +++ pci_pci.c   (working copy)
> > @@ -162,8 +162,13 @@ pcib_write_windows(struct pcib_softc *sc, int mask
> >  {
> >        device_t dev;
> >        uint32_t val;
> > +       uint16_t cmd;
> >
> >        dev = sc->dev;
> > +       cmd = pci_read_config(dev, PCIR_COMMAND, 2);
> > +       if (cmd & (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN))
> > +               pci_write_config(dev, PCIR_COMMAND,
> > +                   cmd & ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN), 2);
> >        if (sc->io.valid && mask & WIN_IO) {
> >                val = pci_read_config(dev, PCIR_IOBASEL_1, 1);
> >                if ((val & PCIM_BRIO_MASK) == PCIM_BRIO_32) {
> > @@ -192,6 +197,8 @@ pcib_write_windows(struct pcib_softc *sc, int mask
> >                pci_write_config(dev, PCIR_PMBASEL_1, sc->pmem.base >> 16, 2);
> >                pci_write_config(dev, PCIR_PMLIMITL_1, sc->pmem.limit >> 16, 2);
> >        }
> > +       if (cmd & (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN))
> > +               pci_write_config(dev, PCIR_COMMAND, cmd, 2);
> >  }
> >
> >  static void
> > @@ -337,6 +344,9 @@ pcib_probe_windows(struct pcib_softc *sc)
> >                            pci_read_config(dev, PCIR_PMLIMITL_1, 2));
> >                        max = 0xffffffff;
> >                }
> > +               /* XXX: Testing hack */
> > +               if (device_get_unit(sc->sc_dev) == 1)
> 
> i'm assuming that "sc->sc_dev" should be "dev" (this fixes a compilation error).
> 
> > +                       sc->pmem.limit = 0xefffffff;
> >                pcib_alloc_window(sc, &sc->pmem, SYS_RES_MEMORY,
> >                    RF_PREFETCHABLE, max);
> >        }
> 
> that seems to work!
> 
> btw, is my machine a test-pig for an upcoming change to the PCI bus driver?

Can you try out this change.  It is a possible "real" solution (or at least a
stopgap until we start using multipass to untangle the resource mess a bit
further):

Index: dev/acpica/acpi_pcib_pci.c
===================================================================
--- dev/acpica/acpi_pcib_pci.c	(revision 222747)
+++ dev/acpica/acpi_pcib_pci.c	(working copy)
@@ -114,13 +114,16 @@
 acpi_pcib_pci_attach(device_t dev)
 {
     struct acpi_pcib_softc *sc;
+    int error;
 
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
     pcib_attach_common(dev);
     sc = device_get_softc(dev);
     sc->ap_handle = acpi_get_handle(dev);
-    return (acpi_pcib_attach(dev, &sc->ap_prt, sc->ap_pcibsc.secbus));
+    error = acpi_pcib_attach(dev, &sc->ap_prt, sc->ap_pcibsc.secbus);
+    pcib_attach_final(dev);
+    return (error);
 }
 
 static int
Index: dev/pci/pci_pci.c
===================================================================
--- dev/pci/pci_pci.c	(revision 222747)
+++ dev/pci/pci_pci.c	(working copy)
@@ -162,8 +162,13 @@
 {
 	device_t dev;
 	uint32_t val;
+	uint16_t cmd;
 
 	dev = sc->dev;
+	cmd = pci_read_config(dev, PCIR_COMMAND, 2);
+	if (cmd & (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN))
+		pci_write_config(dev, PCIR_COMMAND,
+		    cmd & ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN), 2);
 	if (sc->io.valid && mask & WIN_IO) {
 		val = pci_read_config(dev, PCIR_IOBASEL_1, 1);
 		if ((val & PCIM_BRIO_MASK) == PCIM_BRIO_32) {
@@ -192,6 +197,8 @@
 		pci_write_config(dev, PCIR_PMBASEL_1, sc->pmem.base >> 16, 2);
 		pci_write_config(dev, PCIR_PMLIMITL_1, sc->pmem.limit >> 16, 2);
 	}
+	if (cmd & (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN))
+		pci_write_config(dev, PCIR_COMMAND, cmd, 2);
 }
 
 static void
@@ -231,7 +238,7 @@
 		    w->name, (uintmax_t)w->base, (uintmax_t)w->limit);
 		w->base = max_address;
 		w->limit = 0;
-		pcib_write_windows(sc, w->mask);
+		sc->win_deferred |= w->mask;
 		return;
 	}
 	pcib_activate_window(sc, type);
@@ -690,22 +697,33 @@
      */
 }
 
+void
+pcib_attach_final(device_t dev)
+{
+#ifdef NEW_PCIB
+    struct pcib_softc	*sc;
+
+    sc = device_get_softc(dev);
+    if (sc->win_deferred) {
+	    pcib_write_windows(sc, sc->win_deferred);
+	    sc->win_deferred = 0;
+    }
+#endif
+}
+
 int
 pcib_attach(device_t dev)
 {
     struct pcib_softc	*sc;
-    device_t		child;
+    int error;
 
     pcib_attach_common(dev);
     sc = device_get_softc(dev);
-    if (sc->secbus != 0) {
-	child = device_add_child(dev, "pci", sc->secbus);
-	if (child != NULL)
-	    return(bus_generic_attach(dev));
-    }
-
-    /* no secondary bus; we should have fixed this */
-    return(0);
+    if (sc->secbus != 0)
+	device_add_child(dev, "pci", sc->secbus);
+    error = bus_generic_attach(dev);
+    pcib_attach_final(dev);
+    return (error);
 }
 
 int
@@ -1020,7 +1038,8 @@
 	    ("start address is not aligned"));
 	KASSERT((w->limit & ((1ul << w->step) - 1)) == (1ul << w->step) - 1,
 	    ("end address is not aligned"));
-	pcib_write_windows(sc, w->mask);
+	if (!(sc->win_deferred & w->mask))
+		pcib_write_windows(sc, w->mask);
 	return (0);
 }
 
Index: dev/pci/pcib_private.h
===================================================================
--- dev/pci/pcib_private.h	(revision 222747)
+++ dev/pci/pcib_private.h	(working copy)
@@ -75,6 +75,7 @@
     struct pcib_window io;	/* I/O port window */
     struct pcib_window mem;	/* memory window */
     struct pcib_window pmem;	/* prefetchable memory window */
+    u_int	win_deferred;
 #else
     pci_addr_t	pmembase;	/* base address of prefetchable memory */
     pci_addr_t	pmemlimit;	/* topmost address of prefetchable memory */
@@ -94,6 +95,7 @@
     int slot, int func, uint8_t *busnum);
 int		pcib_attach(device_t dev);
 void		pcib_attach_common(device_t dev);
+void		pcib_attach_final(device_t dev);
 int		pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result);
 int		pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value);
 struct resource *pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, 
Index: powerpc/ofw/ofw_pcib_pci.c
===================================================================
--- powerpc/ofw/ofw_pcib_pci.c	(revision 222747)
+++ powerpc/ofw/ofw_pcib_pci.c	(working copy)
@@ -126,6 +126,7 @@
 ofw_pcib_pci_attach(device_t dev)
 {
 	struct ofw_pcib_softc *sc;
+	int error;
 
 	sc = device_get_softc(dev);
 	sc->ops_pcib_sc.dev = dev;
@@ -138,7 +139,9 @@
 
 	device_add_child(dev, "pci", -1);
 
-	return (bus_generic_attach(dev));
+	error = bus_generic_attach(dev);
+	pcib_attach_final(dev);
+	return (error);
 }
 
 static phandle_t
Index: sparc64/pci/ofw_pcib.c
===================================================================
--- sparc64/pci/ofw_pcib.c	(revision 222747)
+++ sparc64/pci/ofw_pcib.c	(working copy)
@@ -116,6 +116,7 @@
 ofw_pcib_attach(device_t dev)
 {
 	struct ofw_pcib_gen_softc *sc;
+	int error;
 
 	sc = device_get_softc(dev);
 
@@ -135,5 +136,7 @@
 	ofw_pcib_gen_setup(dev);
 	pcib_attach_common(dev);
 	device_add_child(dev, "pci", -1);
-	return (bus_generic_attach(dev));
+	error = bus_generic_attach(dev);
+	pcib_attach_final(dev);
+	return (error);
 }

-- 
John Baldwin


More information about the freebsd-current mailing list