Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 2 Mar 2012 20:38:05 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r232403 - in head/sys: dev/acpica dev/cardbus dev/pci powerpc/ofw sparc64/pci
Message-ID:  <201203022038.q22Kc5vd046376@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Fri Mar  2 20:38:04 2012
New Revision: 232403
URL: http://svn.freebsd.org/changeset/base/232403

Log:
  - 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.
  
  MFC after:	2 weeks

Modified:
  head/sys/dev/acpica/acpi_pci.c
  head/sys/dev/cardbus/cardbus.c
  head/sys/dev/pci/pci.c
  head/sys/dev/pci/pci_private.h
  head/sys/powerpc/ofw/ofw_pcibus.c
  head/sys/sparc64/pci/ofw_pcibus.c

Modified: head/sys/dev/acpica/acpi_pci.c
==============================================================================
--- head/sys/dev/acpica/acpi_pci.c	Fri Mar  2 20:34:15 2012	(r232402)
+++ head/sys/dev/acpica/acpi_pci.c	Fri Mar  2 20:38:04 2012	(r232403)
@@ -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);
@@ -276,7 +277,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
@@ -286,9 +291,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: head/sys/dev/cardbus/cardbus.c
==============================================================================
--- head/sys/dev/cardbus/cardbus.c	Fri Mar  2 20:34:15 2012	(r232402)
+++ head/sys/dev/cardbus/cardbus.c	Fri Mar  2 20:38:04 2012	(r232403)
@@ -316,6 +316,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_driver_added,	cardbus_driver_added),
 

Modified: head/sys/dev/pci/pci.c
==============================================================================
--- head/sys/dev/pci/pci.c	Fri Mar  2 20:34:15 2012	(r232402)
+++ head/sys/dev/pci/pci.c	Fri Mar  2 20:38:04 2012	(r232403)
@@ -70,6 +70,19 @@ __FBSDID("$FreeBSD$");
 #include "pcib_if.h"
 #include "pci_if.h"
 
+/*
+ * 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.
+ */
+#ifdef PAE
+#define	PCI_DMA_BOUNDARY	(1u << 31)
+#else
+#define	PCI_DMA_BOUNDARY	((bus_size_t)((uint64_t)1 << 32))
+#endif
+
 #define	PCIR_IS_BIOS(cfg, reg)						\
 	(((cfg)->hdrtype == PCIM_HDRTYPE_NORMAL && reg == PCIR_BIOS) ||	\
 	 ((cfg)->hdrtype == PCIM_HDRTYPE_BRIDGE && reg == PCIR_BIOS_1))
@@ -95,6 +108,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 +151,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 +188,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);
@@ -3124,10 +3139,41 @@ pci_probe(device_t dev)
 	return (BUS_PROBE_GENERIC);
 }
 
+int
+pci_attach_common(device_t dev)
+{
+	struct pci_softc *sc;
+	int busno, domain, error;
+
+	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);
+	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
+			sc->sc_dma_tag_valid = 1;
+	}
+	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
@@ -3137,9 +3183,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));
 }
@@ -4226,6 +4269,16 @@ 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);
+
+	if (sc->sc_dma_tag_valid)
+		return (sc->sc_dma_tag);
+	return (bus_generic_get_dma_tag(bus, dev));
+}
+
 uint32_t
 pci_read_config_method(device_t dev, device_t child, int reg, int width)
 {

Modified: head/sys/dev/pci/pci_private.h
==============================================================================
--- head/sys/dev/pci/pci_private.h	Fri Mar  2 20:34:15 2012	(r232402)
+++ head/sys/dev/pci/pci_private.h	Fri Mar  2 20:38:04 2012	(r232403)
@@ -38,6 +38,11 @@
  */
 DECLARE_CLASS(pci_driver);
 
+struct pci_softc {
+	bus_dma_tag_t sc_dma_tag;
+	int	sc_dma_tag_valid;
+};
+
 extern int 	pci_do_power_resume;
 extern int 	pci_do_power_suspend;
 
@@ -46,6 +51,7 @@ void		pci_add_children(device_t dev, int
 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_delete_child(device_t dev, device_t child);
 void		pci_driver_added(device_t dev, driver_t *driver);
 int		pci_print_child(device_t dev, device_t child);

Modified: head/sys/powerpc/ofw/ofw_pcibus.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_pcibus.c	Fri Mar  2 20:34:15 2012	(r232402)
+++ head/sys/powerpc/ofw/ofw_pcibus.c	Fri Mar  2 20:38:04 2012	(r232403)
@@ -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: head/sys/sparc64/pci/ofw_pcibus.c
==============================================================================
--- head/sys/sparc64/pci/ofw_pcibus.c	Fri Mar  2 20:34:15 2012	(r232402)
+++ head/sys/sparc64/pci/ofw_pcibus.c	Fri Mar  2 20:38:04 2012	(r232403)
@@ -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?201203022038.q22Kc5vd046376>