Date: Wed, 04 Mar 2009 14:09:19 -0500 From: Michael Butler <imb@protected-networks.net> To: John Baldwin <jhb@freebsd.org> Cc: freebsd-current@freebsd.org Subject: Re: pci regression: "panic: resource_list_alloc: resource entry is busy" Message-ID: <49AED1DF.2060801@protected-networks.net> In-Reply-To: <200903041034.06931.jhb@freebsd.org> References: <49ADE16C.9030805@protected-networks.net> <200903041011.24606.jhb@freebsd.org> <200903041034.06931.jhb@freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 John Baldwin wrote: > Probably at some point the agp and drm drivers for Intel will be merged which > would fix this, but this patch should help for now. We used to be leaking > a small portion of KVA due to this problem before. > > --- //depot/vendor/freebsd/src/sys/dev/pci/vga_pci.c 2008/09/19 19:15:30 > +++ //depot/user/jhb/acpipci/dev/pci/vga_pci.c 2009/03/04 15:32:08 > @@ -42,12 +42,20 @@ > #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 > @@ -130,7 +138,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)); > } > > @@ -138,6 +166,37 @@ > 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)); > } > This works perfectly, thanks! :-) Michael -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (FreeBSD) iEYEARECAAYFAkmu0d8ACgkQQv9rrgRC1JKdQwCgzcOUZGUkAH+ynHyU8eyheGBJ pagAnRKOf6s/9KaMewqDRtUc32CXtxpw =SQHc -----END PGP SIGNATURE-----
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?49AED1DF.2060801>