Date: Fri, 23 Mar 2012 20:47:50 +0000 (UTC) From: John Baldwin <jhb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r233394 - in stable/8/sys: dev/acpica dev/cardbus dev/pci i386/conf powerpc/ofw sparc64/pci Message-ID: <201203232047.q2NKloX5093500@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jhb Date: Fri Mar 23 20:47:49 2012 New Revision: 233394 URL: http://svn.freebsd.org/changeset/base/233394 Log: MFC 232403,232667: - Add a bus_dma tag to each PCI bus that is a child of a Host-PCI bridge. The tag enforces a single restriction that all DMA transactions must not cross a 4GB boundary. Note that while this restriction technically only applies to PCI-express, this change applies it to all PCI devices as it is simpler to implement that way and errs on the side of caution. - Add a softc structure for PCI bus devices to hold the bus_dma tag and a new pci_attach_common() routine that performs actions common to the attach phase of all PCI bus drivers. Right now this only consists of a bootverbose printf and the allocate of a bus_dma tag if necessary. - Adjust all PCI bus drivers to allocate a PCI bus softc and to call pci_attach_common() from their attach routines. Modified: stable/8/sys/dev/acpica/acpi_pci.c stable/8/sys/dev/cardbus/cardbus.c stable/8/sys/dev/pci/pci.c stable/8/sys/dev/pci/pci_private.h stable/8/sys/powerpc/ofw/ofw_pcibus.c stable/8/sys/sparc64/pci/ofw_pcibus.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/boot/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/e1000/ (props changed) stable/8/sys/i386/conf/XENHVM (props changed) Modified: stable/8/sys/dev/acpica/acpi_pci.c ============================================================================== --- stable/8/sys/dev/acpica/acpi_pci.c Fri Mar 23 20:47:25 2012 (r233393) +++ stable/8/sys/dev/acpica/acpi_pci.c Fri Mar 23 20:47:49 2012 (r233394) @@ -99,7 +99,8 @@ static device_method_t acpi_pci_methods[ static devclass_t pci_devclass; -DEFINE_CLASS_1(pci, acpi_pci_driver, acpi_pci_methods, 0, pci_driver); +DEFINE_CLASS_1(pci, acpi_pci_driver, acpi_pci_methods, sizeof(struct pci_softc), + pci_driver); DRIVER_MODULE(acpi_pci, pcib, acpi_pci_driver, pci_devclass, 0, 0); MODULE_DEPEND(acpi_pci, acpi, 1, 1, 1); MODULE_DEPEND(acpi_pci, pci, 1, 1, 1); @@ -288,7 +289,11 @@ acpi_pci_probe(device_t dev) static int acpi_pci_attach(device_t dev) { - int busno, domain; + int busno, domain, error; + + error = pci_attach_common(dev); + if (error) + return (error); /* * Since there can be multiple independantly numbered PCI @@ -298,9 +303,6 @@ acpi_pci_attach(device_t dev) */ domain = pcib_get_domain(dev); busno = pcib_get_bus(dev); - if (bootverbose) - device_printf(dev, "domain=%d, physical bus=%d\n", - domain, busno); /* * First, PCI devices are added as in the normal PCI bus driver. Modified: stable/8/sys/dev/cardbus/cardbus.c ============================================================================== --- stable/8/sys/dev/cardbus/cardbus.c Fri Mar 23 20:47:25 2012 (r233393) +++ stable/8/sys/dev/cardbus/cardbus.c Fri Mar 23 20:47:49 2012 (r233394) @@ -345,6 +345,7 @@ static device_method_t cardbus_methods[] DEVMETHOD(device_resume, cardbus_resume), /* Bus interface */ + DEVMETHOD(bus_get_dma_tag, bus_generic_get_dma_tag), DEVMETHOD(bus_read_ivar, cardbus_read_ivar), DEVMETHOD(bus_write_ivar, pci_write_ivar), DEVMETHOD(bus_driver_added, cardbus_driver_added), Modified: stable/8/sys/dev/pci/pci.c ============================================================================== --- stable/8/sys/dev/pci/pci.c Fri Mar 23 20:47:25 2012 (r233393) +++ stable/8/sys/dev/pci/pci.c Fri Mar 23 20:47:49 2012 (r233394) @@ -76,6 +76,21 @@ __FBSDID("$FreeBSD$"); #define ACPI_PWR_FOR_SLEEP(x, y, z) #endif +/* + * XXX: Due to a limitation of the bus_dma_tag_create() API, we cannot + * specify a 4GB boundary on 32-bit targets. Usually this does not + * matter as it is ok to use a boundary of 0 on these systems. + * However, in the case of PAE, DMA addresses can cross a 4GB + * boundary, so as a workaround use a 2GB boundary. + */ +#if (BUS_SPACE_MAXADDR > 0xFFFFFFFF) +#ifdef PAE +#define PCI_DMA_BOUNDARY 0x80000000 +#else +#define PCI_DMA_BOUNDARY 0x100000000 +#endif +#endif + static pci_addr_t pci_mapbase(uint64_t mapreg); static const char *pci_maptype(uint64_t mapreg); static int pci_mapsize(uint64_t testval); @@ -95,6 +110,7 @@ static void pci_load_vendor_data(void); static int pci_describe_parse_line(char **ptr, int *vendor, int *device, char **desc); static char *pci_describe_device(device_t dev); +static bus_dma_tag_t pci_get_dma_tag(device_t bus, device_t dev); static int pci_modevent(module_t mod, int what, void *arg); static void pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg); @@ -137,6 +153,7 @@ static device_method_t pci_methods[] = { DEVMETHOD(bus_setup_intr, pci_setup_intr), DEVMETHOD(bus_teardown_intr, pci_teardown_intr), + DEVMETHOD(bus_get_dma_tag, pci_get_dma_tag), DEVMETHOD(bus_get_resource_list,pci_get_resource_list), DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), @@ -173,7 +190,7 @@ static device_method_t pci_methods[] = { DEVMETHOD_END }; -DEFINE_CLASS_0(pci, pci_driver, pci_methods, 0); +DEFINE_CLASS_0(pci, pci_driver, pci_methods, sizeof(struct pci_softc)); static devclass_t pci_devclass; DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, 0); @@ -2925,10 +2942,49 @@ pci_probe(device_t dev) return (BUS_PROBE_GENERIC); } +int +pci_attach_common(device_t dev) +{ + struct pci_softc *sc; + int busno, domain; +#ifdef PCI_DMA_BOUNDARY + int error, tag_valid; +#endif + + sc = device_get_softc(dev); + domain = pcib_get_domain(dev); + busno = pcib_get_bus(dev); + if (bootverbose) + device_printf(dev, "domain=%d, physical bus=%d\n", + domain, busno); +#ifdef PCI_DMA_BOUNDARY + tag_valid = 0; + if (device_get_devclass(device_get_parent(device_get_parent(dev))) != + devclass_find("pci")) { + error = bus_dma_tag_create(bus_get_dma_tag(dev), 1, + PCI_DMA_BOUNDARY, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, + NULL, NULL, BUS_SPACE_MAXSIZE, BUS_SPACE_UNRESTRICTED, + BUS_SPACE_MAXSIZE, 0, NULL, NULL, &sc->sc_dma_tag); + if (error) + device_printf(dev, "Failed to create DMA tag: %d\n", + error); + else + tag_valid = 1; + } + if (!tag_valid) +#endif + sc->sc_dma_tag = bus_get_dma_tag(dev); + return (0); +} + static int pci_attach(device_t dev) { - int busno, domain; + int busno, domain, error; + + error = pci_attach_common(dev); + if (error) + return (error); /* * Since there can be multiple independantly numbered PCI @@ -2938,9 +2994,6 @@ pci_attach(device_t dev) */ domain = pcib_get_domain(dev); busno = pcib_get_bus(dev); - if (bootverbose) - device_printf(dev, "domain=%d, physical bus=%d\n", - domain, busno); pci_add_children(dev, domain, busno, sizeof(struct pci_devinfo)); return (bus_generic_attach(dev)); } @@ -3963,6 +4016,14 @@ pci_get_resource_list (device_t dev, dev return (&dinfo->resources); } +bus_dma_tag_t +pci_get_dma_tag(device_t bus, device_t dev) +{ + struct pci_softc *sc = device_get_softc(bus); + + return (sc->sc_dma_tag); +} + uint32_t pci_read_config_method(device_t dev, device_t child, int reg, int width) { Modified: stable/8/sys/dev/pci/pci_private.h ============================================================================== --- stable/8/sys/dev/pci/pci_private.h Fri Mar 23 20:47:25 2012 (r233393) +++ stable/8/sys/dev/pci/pci_private.h Fri Mar 23 20:47:49 2012 (r233394) @@ -38,11 +38,16 @@ */ DECLARE_CLASS(pci_driver); +struct pci_softc { + bus_dma_tag_t sc_dma_tag; +}; + void pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size); void pci_add_child(device_t bus, struct pci_devinfo *dinfo); void pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask); +int pci_attach_common(device_t dev); void pci_driver_added(device_t dev, driver_t *driver); int pci_print_child(device_t dev, device_t child); void pci_probe_nomatch(device_t dev, device_t child); Modified: stable/8/sys/powerpc/ofw/ofw_pcibus.c ============================================================================== --- stable/8/sys/powerpc/ofw/ofw_pcibus.c Fri Mar 23 20:47:25 2012 (r233393) +++ stable/8/sys/powerpc/ofw/ofw_pcibus.c Fri Mar 23 20:47:49 2012 (r233394) @@ -95,8 +95,8 @@ struct ofw_pcibus_devinfo { static devclass_t pci_devclass; -DEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods, 1 /* no softc */, - pci_driver); +DEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods, + sizeof(struct pci_softc), pci_driver); DRIVER_MODULE(ofw_pcibus, pcib, ofw_pcibus_driver, pci_devclass, 0, 0); MODULE_VERSION(ofw_pcibus, 1); MODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1); @@ -116,12 +116,13 @@ static int ofw_pcibus_attach(device_t dev) { u_int busno, domain; + int error; + error = pci_attach_common(dev); + if (error) + return (error); domain = pcib_get_domain(dev); busno = pcib_get_bus(dev); - if (bootverbose) - device_printf(dev, "domain=%d, physical bus=%d\n", - domain, busno); /* * Attach those children represented in the device tree. Modified: stable/8/sys/sparc64/pci/ofw_pcibus.c ============================================================================== --- stable/8/sys/sparc64/pci/ofw_pcibus.c Fri Mar 23 20:47:25 2012 (r233393) +++ stable/8/sys/sparc64/pci/ofw_pcibus.c Fri Mar 23 20:47:49 2012 (r233394) @@ -100,8 +100,8 @@ struct ofw_pcibus_devinfo { static devclass_t pci_devclass; -DEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods, 1 /* no softc */, - pci_driver); +DEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods, + sizeof(struct pci_softc), pci_driver); EARLY_DRIVER_MODULE(ofw_pcibus, pcib, ofw_pcibus_driver, pci_devclass, 0, 0, BUS_PASS_BUS); MODULE_VERSION(ofw_pcibus, 1); @@ -230,13 +230,14 @@ ofw_pcibus_attach(device_t dev) phandle_t node, child; uint32_t clock; u_int busno, domain, func, slot; + int error; + error = pci_attach_common(dev); + if (error) + return (error); pcib = device_get_parent(dev); domain = pcib_get_domain(dev); busno = pcib_get_bus(dev); - if (bootverbose) - device_printf(dev, "domain=%d, physical bus=%d\n", - domain, busno); node = ofw_bus_get_node(dev); /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203232047.q2NKloX5093500>