[PANIC] recent 7.2-STABLE when probing drm
Kostik Belousov
kostikbel at gmail.com
Tue May 5 13:56:09 UTC 2009
On Tue, May 05, 2009 at 01:35:27PM +0100, Gavin Atkinson wrote:
> On Tue, 2009-05-05 at 15:12 +0300, Kostik Belousov wrote:
> > On Tue, May 05, 2009 at 12:12:31PM +0100, Gavin Atkinson wrote:
> > > On Tue, 2009-05-05 at 13:06 +0200, Guido Falsi wrote:
> > > > Hi!
> > > >
> > > > I'm using FreeBSD/i386 stable on a HP DC7800 PC.
> > > >
> > > > It has an Intel Q35 graphic chip.
> > > >
> > > > After upgrading to a recent stable I experienced a pani on boot, just
> > > > after probing drm.
> > > >
> > > > I investigated a little and found out that reverting the file
> > > >
> > > > src/sys/dev/pci/pci.c
> > > >
> > > > to rev. 1.355.2.9 (SVN Rev 190092) solves the crash.
> > > >
> > > > I could not investigatte urther right away, but some regression was
> > > > introduced with this rev.
> > > >
> > > > Is any more information needed?
> > >
> > > When it panics, can you please type "bt" (assuming you have the debugger
> > > compiled in) and show the output?
> >
> > I have this too. I have dump too.
> >
> > drm0: <Intel i945GM> on vgapci0
> > panic: resource_list_alloc: resource entry is busy
> > KDB: stack backtrace:
> > db_trace_self_wrapper(c07214ff,c2b46764,c04c928f,c071f823,c078b080,...) at 0xc044df46 = db_trace_self_wrapper+0x26
> > kdb_backtrace(c071f823,c078b080,c07211b1,c2b46770,c2b46770,...) at 0xc04f41f9 = kdb_backtrace+0x29
> > panic(c07211b1,3,10,c04e9484,c2e37000,...) at 0xc04c928f = panic+0xaf
> > resource_list_alloc(c2cffb04,c2d00a80,c2d00c80,3,c2d2a1fc,...) at 0xc04f0c06 = resource_list_alloc+0xd6
> > pci_alloc_resource(c2d00a80,c2d00c80,3,c2d2a1fc,0,ffffffff,1,4) at 0xc045a2d1 = pci_alloc_resource+0x581
> > bus_alloc_resource(c2d00c80,3,c2d2a1fc,0,ffffffff,...) at 0xc04f0a8c = bus_alloc_resource+0x7c
> > vga_pci_alloc_resource(c2d00c80,c2cfa080,3,c2d2a1fc,0,ffffffff,1,4) at 0xc04600ab = vga_pci_alloc_resource+0x3b
> [...]
>
> I wonder if r189373 also needs merging?
Thanks for the hint. We need both r183095 and r189373, but the
actual bugfix is r189373, as you rightly pointed out. Below is the patch
that works for me.
Index: dev/pci/vga_pci.c
===================================================================
--- dev/pci/vga_pci.c (revision 191816)
+++ dev/pci/vga_pci.c (working copy)
@@ -42,10 +42,22 @@
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
+struct vga_resource {
+ struct resource *vr_res;
+ int vr_refs;
+};
+
+struct vga_pci_softc {
+ device_t vga_msi_child; /* Child driver using MSI. */
+ struct vga_resource vga_res[PCIR_MAX_BAR_0 + 1];
+};
+
static int
vga_pci_probe(device_t dev)
{
@@ -110,7 +122,27 @@
vga_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
+ struct vga_pci_softc *sc;
+ int bar;
+ switch (type) {
+ case SYS_RES_MEMORY:
+ case SYS_RES_IOPORT:
+ /*
+ * For BARs, we cache the resource so that we only allocate it
+ * from the PCI bus once.
+ */
+ bar = PCI_RID2BAR(*rid);
+ if (bar < 0 || bar > PCIR_MAX_BAR_0)
+ return (NULL);
+ sc = device_get_softc(dev);
+ if (sc->vga_res[bar].vr_res == NULL)
+ sc->vga_res[bar].vr_res = bus_alloc_resource(dev, type,
+ rid, start, end, count, flags);
+ if (sc->vga_res[bar].vr_res != NULL)
+ sc->vga_res[bar].vr_refs++;
+ return (sc->vga_res[bar].vr_res);
+ }
return (bus_alloc_resource(dev, type, rid, start, end, count, flags));
}
@@ -118,7 +150,38 @@
vga_pci_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
+ struct vga_pci_softc *sc;
+ int bar, error;
+ switch (type) {
+ case SYS_RES_MEMORY:
+ case SYS_RES_IOPORT:
+ /*
+ * For BARs, we release the resource from the PCI bus
+ * when the last child reference goes away.
+ */
+ bar = PCI_RID2BAR(rid);
+ if (bar < 0 || bar > PCIR_MAX_BAR_0)
+ return (EINVAL);
+ sc = device_get_softc(dev);
+ if (sc->vga_res[bar].vr_res == NULL)
+ return (EINVAL);
+ KASSERT(sc->vga_res[bar].vr_res == r,
+ ("vga_pci resource mismatch"));
+ if (sc->vga_res[bar].vr_refs > 1) {
+ sc->vga_res[bar].vr_refs--;
+ return (0);
+ }
+ KASSERT(sc->vga_res[bar].vr_refs > 0,
+ ("vga_pci resource reference count underflow"));
+ error = bus_release_resource(dev, type, rid, r);
+ if (error == 0) {
+ sc->vga_res[bar].vr_res = NULL;
+ sc->vga_res[bar].vr_refs = 0;
+ }
+ return (error);
+ }
+
return (bus_release_resource(dev, type, rid, r));
}
@@ -176,6 +239,21 @@
}
static int
+vga_pci_get_vpd_ident(device_t dev, device_t child, const char **identptr)
+{
+
+ return (pci_get_vpd_ident(dev, identptr));
+}
+
+static int
+vga_pci_get_vpd_readonly(device_t dev, device_t child, const char *kw,
+ const char **vptr)
+{
+
+ return (pci_get_vpd_readonly(dev, kw, vptr));
+}
+
+static int
vga_pci_set_powerstate(device_t dev, device_t child, int state)
{
@@ -210,6 +288,77 @@
return (pci_find_extcap(dev, capability, capreg));
}
+static int
+vga_pci_alloc_msi(device_t dev, device_t child, int *count)
+{
+ struct vga_pci_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ if (sc->vga_msi_child != NULL)
+ return (EBUSY);
+ error = pci_alloc_msi(dev, count);
+ if (error == 0)
+ sc->vga_msi_child = child;
+ return (error);
+}
+
+static int
+vga_pci_alloc_msix(device_t dev, device_t child, int *count)
+{
+ struct vga_pci_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ if (sc->vga_msi_child != NULL)
+ return (EBUSY);
+ error = pci_alloc_msix(dev, count);
+ if (error == 0)
+ sc->vga_msi_child = child;
+ return (error);
+}
+
+static int
+vga_pci_remap_msix(device_t dev, device_t child, int count,
+ const u_int *vectors)
+{
+ struct vga_pci_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->vga_msi_child != child)
+ return (ENXIO);
+ return (pci_remap_msix(dev, count, vectors));
+}
+
+static int
+vga_pci_release_msi(device_t dev, device_t child)
+{
+ struct vga_pci_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ if (sc->vga_msi_child != child)
+ return (ENXIO);
+ error = pci_release_msi(dev);
+ if (error == 0)
+ sc->vga_msi_child = NULL;
+ return (error);
+}
+
+static int
+vga_pci_msi_count(device_t dev, device_t child)
+{
+
+ return (pci_msi_count(dev));
+}
+
+static int
+vga_pci_msix_count(device_t dev, device_t child)
+{
+
+ return (pci_msix_count(dev));
+}
+
static device_method_t vga_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, vga_pci_probe),
@@ -236,10 +385,18 @@
DEVMETHOD(pci_disable_busmaster, vga_pci_disable_busmaster),
DEVMETHOD(pci_enable_io, vga_pci_enable_io),
DEVMETHOD(pci_disable_io, vga_pci_disable_io),
+ DEVMETHOD(pci_get_vpd_ident, vga_pci_get_vpd_ident),
+ DEVMETHOD(pci_get_vpd_readonly, vga_pci_get_vpd_readonly),
DEVMETHOD(pci_get_powerstate, vga_pci_get_powerstate),
DEVMETHOD(pci_set_powerstate, vga_pci_set_powerstate),
DEVMETHOD(pci_assign_interrupt, vga_pci_assign_interrupt),
DEVMETHOD(pci_find_extcap, vga_pci_find_extcap),
+ DEVMETHOD(pci_alloc_msi, vga_pci_alloc_msi),
+ DEVMETHOD(pci_alloc_msix, vga_pci_alloc_msix),
+ DEVMETHOD(pci_remap_msix, vga_pci_remap_msix),
+ DEVMETHOD(pci_release_msi, vga_pci_release_msi),
+ DEVMETHOD(pci_msi_count, vga_pci_msi_count),
+ DEVMETHOD(pci_msix_count, vga_pci_msix_count),
{ 0, 0 }
};
@@ -247,7 +404,7 @@
static driver_t vga_pci_driver = {
"vgapci",
vga_pci_methods,
- 1,
+ sizeof(struct vga_pci_softc),
};
static devclass_t vga_devclass;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-stable/attachments/20090505/5557bae3/attachment.pgp
More information about the freebsd-stable
mailing list