mpt: Unable to memory map registers
John Baldwin
jhb at freebsd.org
Mon Jun 11 20:23:13 UTC 2012
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<jhb at 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 at 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
More information about the freebsd-stable
mailing list