From owner-svn-src-all@FreeBSD.ORG Tue May 5 14:46:18 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id AE2881065670; Tue, 5 May 2009 14:46:18 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 9982B8FC1B; Tue, 5 May 2009 14:46:18 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n45EkIRI084179; Tue, 5 May 2009 14:46:18 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n45EkIhZ084178; Tue, 5 May 2009 14:46:18 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200905051446.n45EkIhZ084178@svn.freebsd.org> From: John Baldwin Date: Tue, 5 May 2009 14:46:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r191819 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/pci X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 05 May 2009 14:46:19 -0000 Author: jhb Date: Tue May 5 14:46:18 2009 New Revision: 191819 URL: http://svn.freebsd.org/changeset/base/191819 Log: MFC: Sync with HEAD - Proxy PCI MSI/MSI-X requests and bus interrupt requests for child devices instead of passing them through directly. This allows child devices to use MSI/MSI-X interrupts. - Proxy PCI VPD requests. - Proxy bus resource allocation requests to allow multiple child devices to share access to a BAR. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/pci/vga_pci.c Modified: stable/7/sys/dev/pci/vga_pci.c ============================================================================== --- stable/7/sys/dev/pci/vga_pci.c Tue May 5 13:48:53 2009 (r191818) +++ stable/7/sys/dev/pci/vga_pci.c Tue May 5 14:46:18 2009 (r191819) @@ -42,10 +42,22 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include +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) { @@ -106,11 +118,47 @@ vga_pci_write_ivar(device_t dev, device_ return (EINVAL); } +static int +vga_pci_setup_intr(device_t dev, device_t child, struct resource *irq, + int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg, + void **cookiep) +{ + return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags, + filter, intr, arg, cookiep)); +} + +static int +vga_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, + void *cookie) +{ + return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie)); +} + static struct resource * 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,6 +166,37 @@ static int 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 +255,21 @@ vga_pci_disable_io(device_t dev, device_ } 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 +304,77 @@ vga_pci_find_extcap(device_t dev, device 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), @@ -221,8 +386,8 @@ static device_method_t vga_pci_methods[] /* Bus interface */ DEVMETHOD(bus_read_ivar, vga_pci_read_ivar), DEVMETHOD(bus_write_ivar, vga_pci_write_ivar), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_setup_intr, vga_pci_setup_intr), + DEVMETHOD(bus_teardown_intr, vga_pci_teardown_intr), DEVMETHOD(bus_alloc_resource, vga_pci_alloc_resource), DEVMETHOD(bus_release_resource, vga_pci_release_resource), @@ -236,10 +401,18 @@ static device_method_t vga_pci_methods[] 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 +420,7 @@ static device_method_t vga_pci_methods[] static driver_t vga_pci_driver = { "vgapci", vga_pci_methods, - 1, + sizeof(struct vga_pci_softc), }; static devclass_t vga_devclass;