On Monday, June 11, 2012 11:25:38 am Andrey Zonov wrote:
> On 6/11/12 6:19 PM, John Baldwin wrote:
> > On Saturday, June 09, 2012 3:06:19 pm Andrey Zonov wrote:
> >> On 6/9/12 9:35 PM, Marius Strobl wrote:
> >>> On Sat, Jun 09, 2012 at 12:58:05PM +0400, Andrey Zonov wrote:
> >>>> On 6/8/12 10:27 PM, John Baldwin wrote:
> >>>>> On Friday, June 08, 2012 11:48:50 am Andrey Zonov wrote:
> >>>>>> On Fri, Jun 8, 2012 at 7:19 PM, John Baldwin<j...@freebsd.org>    
> >>>>>> wrote:
> >>>>>>> On Friday, June 08, 2012 3:14:19 am Andrey Zonov wrote:
> >>>>>>>> On 6/7/12 10:02 PM, Andrey Zonov wrote:
> >>>>>>>>> Hi,
> >>>>>>>>>
> >>>>>>>>> I just upgraded a few machines from 8.2-STABLE (r221983) to 9.0-
> > STABLE
> >>>>>>>>> (r234600) and now they can't find any disk because SAS controller
> >>>>>>>>> cannot
> >>>>>>>>> initialize with the following diagnostic:
> >>>>>>>>>
> >>>>>>>>> mpt0:<LSILogic SAS/SATA Adapter>    port 0xd000-0xd0ff irq 26 at
> > device
> >>>>>>>>> 3.0 on pci6
> >>>>>>>>> mpt0: 0x4000 bytes of rid 0x14 res 3 failed (0, 0xffffffffffffffff).
> >>>>>>>>> mpt0: Unable to memory map registers.
> >>>>>>>>> mpt0: Giving Up.
> >>>>>>>>>
> >>>>>>>>> pciconf -lv:
> >>>>>>>>> mpt0@pci0:6:3:0: class=0x010000 card=0x81dd1043 chip=0x00541000
> >>>>>>>>> rev=0x02
> >>>>>>>>> hdr=0x00
> >>>>>>>>> vendor = 'LSI Logic / Symbios Logic'
> >>>>>>>>> device = 'SAS1068 PCI-X Fusion-MPT SAS'
> >>>>>>>>> class = mass storage
> >>>>>>>>> subclass = SCSI
> >>>>>>>>>
> >>>>>>>>> I tried to boot to latest HEAD and found the same problem. I also
> > tried
> >>>>>>>>> to build kernel with mpt driver from my 8.2. Controller didn't
> >>>>>>>>> initialize with the same diagnostic. So it looks like the problem is
> >>>>>>>>> not
> >>>>>>>>> in mpt driver.
> >>>>>>>>>
> >>>>>>>>> Any help would be appreciated.
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>> +jhb@
> >>>>>>>>
> >>>>>>>> Hi John,
> >>>>>>>>
> >>>>>>>> Could you please help me with the problem above?  It looks like the
> >>>>>>>> problem is in PCI code and you changed things there.
> >>>>>>>
> >>>>>>> Can you get a verbose dmesg?
> >>>>>>>
> >>>>>>
> >>>>>> Yes, it's in attach.
> >>>>>
> >>>>> Can you get the output of 'devinfo -u' and 'devinfo -rv' from a broken
> >>>>> kernel?
> >>>>>
> >>>>
> >>>> Attached.
> >>>>
> >>>>> Can you also try setting 'debug.acpi.disable=sysres' in the loader?
> >>>>>
> >>>>
> >>>> Didn't help.
> >>>>
> >>>
> >>> That's probably due to a typo, the corret loader tunable is
> >>> debug.acpi.disabled=sysres (note the 'd').
> >>>
> >>
> >> This helps, thanks!  Please explain what this means.
> >
> > Well, it's working around a bug in your BIOS, but in this case FreeBSD 
> > should
> > have coped fine and it didn't.  Please try using this patch without that
> > tunable and get a verbose dmesg please:
> 
> Unfortunately didn't work.

Ah, it did work a bit, but it uncovered a larger bug.  I didn't make the
PCI-PCI bridge driver recursively grow windows.  Try this:

Index: sys/dev/pci/pci_pci.c
===================================================================
--- pci_pci.c   (revision 236888)
+++ pci_pci.c   (working copy)
@@ -113,23 +113,27 @@ DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclas
 
 /*
  * Is a resource from a child device sub-allocated from one of our
- * resource managers?
+ * resource managers?  If so, return the associated window.
  */
-static int
+static struct pcib_window *
 pcib_is_resource_managed(struct pcib_softc *sc, int type, struct resource *r)
 {
 
        switch (type) {
        case SYS_RES_IOPORT:
-               return (rman_is_region_manager(r, &sc->io.rman));
+               if (rman_is_region_manager(r, &sc->io.rman))
+                       return (&sc->io);
+               break;
        case SYS_RES_MEMORY:
                /* Prefetchable resources may live in either memory rman. */
                if (rman_get_flags(r) & RF_PREFETCHABLE &&
                    rman_is_region_manager(r, &sc->pmem.rman))
-                       return (1);
-               return (rman_is_region_manager(r, &sc->mem.rman));
+                       return (&sc->pmem);
+               if (rman_is_region_manager(r, &sc->mem.rman))
+                       return (&sc->mem);
+               break;
        }
-       return (0);
+       return (NULL);
 }
 
 static int
@@ -871,6 +875,10 @@ pcib_grow_window(struct pcib_softc *sc, struct pci
                goto updatewin;
        }
 
+       /* Nothing to do if the request fits in the current window. */
+       if (start >= rman_get_start(w->res) && end <= rman_get_end(w->res))
+               return (ENOSPC);
+
        /*
         * See if growing the window would help.  Compute the minimum
         * amount of address space needed on both the front and back
@@ -881,6 +889,10 @@ pcib_grow_window(struct pcib_softc *sc, struct pci
         * edge of the window, grow from the inner edge of the free
         * region.  Otherwise grow from the window boundary.
         *
+        * As a special case, if the new region is an exact region
+        * that is a superset of the current window, align the ends
+        * and make a single adjust request to our parent.
+        *
         * XXX: Special case: if w->res is completely empty and the
         * request size is larger than w->res, we should find the
         * optimal aligned buffer containing w->res and allocate that.
@@ -890,12 +902,22 @@ pcib_grow_window(struct pcib_softc *sc, struct pci
                    "attempting to grow %s window for (%#lx-%#lx,%#lx)\n",
                    w->name, start, end, count);
        align = 1ul << RF_ALIGNMENT(flags);
+       if (start + count - 1 == end && start <= rman_get_start(w->res) &&
+           end >= rman_get_end(w->res)) {
+               start &= (1ul << w->step) - 1;
+               end = roundup2(end + 1, 1ul << w->step) - 1;
+               if (bootverbose)
+                       printf("\twide candidate range: %#lx-%#lx\n",
+                           start, end);
+               error = bus_adjust_resource(sc->dev, type, w->res, start, end);
+               goto adjusted;
+       }
        if (start < rman_get_start(w->res)) {
                if (rman_first_free_region(&w->rman, &start_free, &end_free) !=
                    0 || start_free != rman_get_start(w->res))
-                       end_free = rman_get_start(w->res) - 1;
+                       end_free = rman_get_start(w->res);
                if (end_free > end)
-                       end_free = end;
+                       end_free = end + 1;
 
                /* Move end_free down until it is properly aligned. */
                end_free &= ~(align - 1);
@@ -971,6 +993,7 @@ pcib_grow_window(struct pcib_softc *sc, struct pci
                }
        }
 
+adjusted:
        if (error)
                return (error);
        if (bootverbose)
@@ -1099,10 +1122,25 @@ pcib_adjust_resource(device_t bus, device_t child,
     u_long start, u_long end)
 {
        struct pcib_softc *sc;
+       struct pcib_window *w;
+       int error;
 
        sc = device_get_softc(bus);
-       if (pcib_is_resource_managed(sc, type, r))
-               return (rman_adjust_resource(r, start, end));
+       w = pcib_is_resource_managed(sc, type, r);
+       if (w != NULL) {
+               error = rman_adjust_resource(r, start, end);
+               if (error == 0)
+                       return (error);
+
+               /*
+                * If the initial adjustment fails, try to grow the
+                * window that backs this resource.
+                */
+               if (pcib_grow_window(sc, w, type, start, end, end - start + 1,
+                   rman_get_flags(r)) == 0)
+                       error = rman_adjust_resource(r, start, end);
+               return (error);
+       }
        return (bus_generic_adjust_resource(bus, child, type, r, start, end));
 }
 
@@ -1114,7 +1152,7 @@ pcib_release_resource(device_t dev, device_t child
        int error;
 
        sc = device_get_softc(dev);
-       if (pcib_is_resource_managed(sc, type, r)) {
+       if (pcib_is_resource_managed(sc, type, r) != NULL) {
                if (rman_get_flags(r) & RF_ACTIVE) {
                        error = bus_deactivate_resource(child, type, rid, r);
                        if (error)

-- 
John Baldwin
_______________________________________________
freebsd-stable@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-stable
To unsubscribe, send any mail to "freebsd-stable-unsubscr...@freebsd.org"

Reply via email to