Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153290224
D12582.id35571.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
26 KB
Referenced Files
None
Subscribers
None
D12582.id35571.diff
View Options
Index: head/sys/dev/bhnd/bhnd.h
===================================================================
--- head/sys/dev/bhnd/bhnd.h
+++ head/sys/dev/bhnd/bhnd.h
@@ -220,6 +220,94 @@
};
/**
+ * bhnd(4) DMA address widths.
+ */
+typedef enum {
+ BHND_DMA_ADDR_30BIT = 30, /**< 30-bit DMA */
+ BHND_DMA_ADDR_32BIT = 32, /**< 32-bit DMA */
+ BHND_DMA_ADDR_64BIT = 64, /**< 64-bit DMA */
+} bhnd_dma_addrwidth;
+
+/**
+ * Convert an address width (in bits) to its corresponding mask.
+ */
+#define BHND_DMA_ADDR_BITMASK(_width) \
+ ((_width >= 64) ? ~0ULL : \
+ (_width == 0) ? 0x0 : \
+ ((1ULL << (_width)) - 1)) \
+
+/**
+ * bhnd(4) DMA address translation descriptor.
+ */
+struct bhnd_dma_translation {
+ /**
+ * Host-to-device physical address translation.
+ *
+ * This may be added to the host physical address to produce a device
+ * DMA address.
+ */
+ bhnd_addr_t base_addr;
+
+ /**
+ * Device-addressable address mask.
+ *
+ * This defines the device's DMA address range, excluding any bits
+ * reserved for mapping the address to the base_addr.
+ */
+ bhnd_addr_t addr_mask;
+
+ /**
+ * Device-addressable extended address mask.
+ *
+ * If a per-core bhnd(4) DMA engine supports the 'addrext' control
+ * field, it can be used to provide address bits excluded by addr_mask.
+ *
+ * Support for DMA extended address changes – including coordination
+ * with the core providing DMA translation – is handled transparently by
+ * the DMA engine. For example, on PCI(e) Wi-Fi chipsets, the Wi-Fi
+ * core DMA engine will (in effect) update the PCI core's DMA
+ * sbtopcitranslation base address to map the full address prior to
+ * performing a DMA transaction.
+ */
+ bhnd_addr_t addrext_mask;
+
+ /**
+ * Translation flags (see bhnd_dma_translation_flags)
+ */
+ uint32_t flags;
+};
+
+#define BHND_DMA_TRANSLATION_TABLE_END { 0, 0, 0, 0 }
+
+#define BHND_DMA_IS_TRANSLATION_TABLE_END(_dt) \
+ ((_dt)->base_addr == 0 && (_dt)->addr_mask == 0 && \
+ (_dt)->addrext_mask == 0 && (_dt)->flags == 0)
+
+/**
+ * bhnd(4) DMA address translation flags.
+ */
+enum bhnd_dma_translation_flags {
+ /**
+ * The translation remaps the device's physical address space.
+ *
+ * This is used in conjunction with BHND_DMA_TRANSLATION_BYTESWAPPED to
+ * define a DMA translation that provides byteswapped access to
+ * physical memory on big-endian MIPS SoCs.
+ */
+ BHND_DMA_TRANSLATION_PHYSMAP = (1<<0),
+
+ /**
+ * Provides a byte-swapped mapping; write requests will be byte-swapped
+ * before being written to memory, and read requests will be
+ * byte-swapped before being returned.
+ *
+ * This is primarily used to perform efficient byte swapping of DMA
+ * data on embedded MIPS SoCs executing in big-endian mode.
+ */
+ BHND_DMA_TRANSLATION_BYTESWAPPED = (1<<1),
+};
+
+/**
* A bhnd(4) bus resource.
*
* This provides an abstract interface to per-core resources that may require
@@ -512,6 +600,10 @@
bhnd_nvram_type type);
const struct bhnd_chipid *bhnd_bus_generic_get_chipid(device_t dev,
device_t child);
+int bhnd_bus_generic_get_dma_translation(
+ device_t dev, device_t child, u_int width,
+ uint32_t flags, bus_dma_tag_t *dmat,
+ struct bhnd_dma_translation *translation);
int bhnd_bus_generic_read_board_info(device_t dev,
device_t child,
struct bhnd_board_info *info);
@@ -840,6 +932,38 @@
static inline bhnd_attach_type
bhnd_get_attach_type (device_t dev) {
return (BHND_BUS_GET_ATTACH_TYPE(device_get_parent(dev), dev));
+}
+
+/**
+ * Find the best available DMA address translation capable of mapping a
+ * physical host address to a BHND DMA device address of @p width with
+ * @p flags.
+ *
+ * @param dev A bhnd bus child device.
+ * @param width The address width within which the translation window must
+ * reside (see BHND_DMA_ADDR_*).
+ * @param flags Required translation flags (see BHND_DMA_TRANSLATION_*).
+ * @param[out] dmat On success, will be populated with a DMA tag specifying the
+ * @p translation DMA address restrictions. This argment may be NULL if the DMA
+ * tag is not desired.
+ * the set of valid host DMA addresses reachable via @p translation.
+ * @param[out] translation On success, will be populated with a DMA address
+ * translation descriptor for @p child. This argment may be NULL if the
+ * descriptor is not desired.
+ *
+ * @retval 0 success
+ * @retval ENODEV If DMA is not supported.
+ * @retval ENOENT If no DMA translation matching @p width and @p flags is
+ * available.
+ * @retval non-zero If determining the DMA address translation for @p child
+ * otherwise fails, a regular unix error code will be returned.
+ */
+static inline int
+bhnd_get_dma_translation(device_t dev, u_int width, uint32_t flags,
+ bus_dma_tag_t *dmat, struct bhnd_dma_translation *translation)
+{
+ return (BHND_BUS_GET_DMA_TRANSLATION(device_get_parent(dev), dev, width,
+ flags, dmat, translation));
}
/**
Index: head/sys/dev/bhnd/bhnd_bus_if.m
===================================================================
--- head/sys/dev/bhnd/bhnd_bus_if.m
+++ head/sys/dev/bhnd/bhnd_bus_if.m
@@ -46,6 +46,7 @@
struct bhnd_board_info;
struct bhnd_core_info;
struct bhnd_chipid;
+ struct bhnd_dma_translation;
struct bhnd_devinfo;
struct bhnd_resource;
}
@@ -112,7 +113,7 @@
{
panic("bhnd_bus_get_attach_type unimplemented");
}
-
+
static bhnd_clksrc
bhnd_bus_null_pwrctl_get_clksrc(device_t dev, device_t child,
bhnd_clock clock)
@@ -478,6 +479,41 @@
device_t dev;
device_t child;
} DEFAULT bhnd_bus_null_get_attach_type;
+
+
+/**
+ * Find the best available DMA address translation capable of mapping a
+ * physical host address to a BHND DMA device address of @p width with
+ * @p flags.
+ *
+ * @param dev The parent of @p child.
+ * @param child The bhnd device requesting the DMA address translation.
+ * @param width The address width within which the translation window must
+ * reside (see BHND_DMA_ADDR_*).
+ * @param flags Required translation flags (see BHND_DMA_TRANSLATION_*).
+ * @param[out] dmat On success, will be populated with a DMA tag specifying the
+ * @p translation DMA address restrictions. This argment may be NULL if the DMA
+ * tag is not desired.
+ * the set of valid host DMA addresses reachable via @p translation.
+ * @param[out] translation On success, will be populated with a DMA address
+ * translation descriptor for @p child. This argment may be NULL if the
+ * descriptor is not desired.
+ *
+ * @retval 0 success
+ * @retval ENODEV If DMA is not supported.
+ * @retval ENOENT If no DMA translation matching @p width and @p flags is
+ * available.
+ * @retval non-zero If determining the DMA address translation for @p child
+ * otherwise fails, a regular unix error code will be returned.
+ */
+METHOD int get_dma_translation {
+ device_t dev;
+ device_t child;
+ u_int width;
+ uint32_t flags;
+ bus_dma_tag_t *dmat;
+ struct bhnd_dma_translation *translation;
+} DEFAULT bhnd_bus_generic_get_dma_translation;
/**
* Attempt to read the BHND board identification from the parent bus.
Index: head/sys/dev/bhnd/bhnd_subr.c
===================================================================
--- head/sys/dev/bhnd/bhnd_subr.c
+++ head/sys/dev/bhnd/bhnd_subr.c
@@ -2104,6 +2104,27 @@
panic("missing BHND_BUS_GET_CHIPID()");
}
+/**
+ * Helper function for implementing BHND_BUS_GET_DMA_TRANSLATION().
+ *
+ * If a parent device is available, this implementation delegates the
+ * request to the BHND_BUS_GET_DMA_TRANSLATION() method on the parent of @p dev.
+ *
+ * If no parent device is available, this implementation will panic.
+ */
+int
+bhnd_bus_generic_get_dma_translation(device_t dev, device_t child, u_int width,
+ uint32_t flags, bus_dma_tag_t *dmat,
+ struct bhnd_dma_translation *translation)
+{
+ if (device_get_parent(dev) != NULL) {
+ return (BHND_BUS_GET_DMA_TRANSLATION(device_get_parent(dev),
+ child, width, flags, dmat, translation));
+ }
+
+ panic("missing BHND_BUS_GET_DMA_TRANSLATION()");
+}
+
/* nvram board_info population macros for bhnd_bus_generic_read_board_info() */
#define BHND_GV(_dest, _name) \
bhnd_nvram_getvar_uint(child, BHND_NVAR_ ## _name, &_dest, \
Index: head/sys/dev/bhnd/bhndb/bhndb.h
===================================================================
--- head/sys/dev/bhnd/bhndb/bhndb.h
+++ head/sys/dev/bhnd/bhndb/bhndb.h
@@ -107,12 +107,13 @@
/**
* Bridge hardware configuration.
*
- * Provides the bridge's register/address mappings, and the resources
- * via which those mappings may be accessed.
+ * Provides the bridge's DMA address translation descriptions, register/address
+ * mappings, and the resources via which those mappings may be accessed.
*/
struct bhndb_hwcfg {
- const struct resource_spec *resource_specs;
- const struct bhndb_regwin *register_windows;
+ const struct resource_spec *resource_specs; /**< resources required by our register windows */
+ const struct bhndb_regwin *register_windows; /**< register window table */
+ const struct bhnd_dma_translation *dma_translations; /**< DMA address translation table, or NULL if DMA is not supported */
};
/**
Index: head/sys/dev/bhnd/bhndb/bhndb.c
===================================================================
--- head/sys/dev/bhnd/bhndb/bhndb.c
+++ head/sys/dev/bhnd/bhndb/bhndb.c
@@ -2040,13 +2040,93 @@
}
/**
+ * Default bhndb(4) implementation of BHND_BUS_GET_DMA_TRANSLATION().
+ */
+static inline int
+bhndb_get_dma_translation(device_t dev, device_t child, u_int width,
+ uint32_t flags, bus_dma_tag_t *dmat,
+ struct bhnd_dma_translation *translation)
+{
+ struct bhndb_softc *sc;
+ const struct bhndb_hwcfg *hwcfg;
+ const struct bhnd_dma_translation *match;
+ bus_dma_tag_t match_dmat;
+ bhnd_addr_t addr_mask, match_addr_mask;
+
+ sc = device_get_softc(dev);
+ hwcfg = sc->bus_res->cfg;
+
+ /* Is DMA supported? */
+ if (sc->bus_res->res->dma_tags == NULL)
+ return (ENODEV);
+
+ /* Find the best matching descriptor for the requested type */
+ addr_mask = BHND_DMA_ADDR_BITMASK(width);
+
+ match = NULL;
+ match_addr_mask = 0x0;
+ match_dmat = NULL;
+
+ for (size_t i = 0; i < sc->bus_res->res->num_dma_tags; i++) {
+ const struct bhnd_dma_translation *dwin;
+ bhnd_addr_t masked;
+
+ dwin = &hwcfg->dma_translations[i];
+
+ /* The base address must be device addressable */
+ if ((dwin->base_addr & addr_mask) != dwin->base_addr)
+ continue;
+
+ /* The flags must match */
+ if ((dwin->flags & flags) != flags)
+ continue;
+
+ /* The window must cover at least part of our addressable
+ * range */
+ masked = (dwin->addr_mask | dwin->addrext_mask) & addr_mask;
+ if (masked == 0)
+ continue;
+
+ /* Is this a better match? */
+ if (match == NULL || masked > match_addr_mask) {
+ match = dwin;
+ match_addr_mask = masked;
+ match_dmat = sc->bus_res->res->dma_tags[i];
+ }
+ }
+
+ if (match == NULL || match_addr_mask == 0)
+ return (ENOENT);
+
+ if (dmat != NULL)
+ *dmat = match_dmat;
+
+ if (translation != NULL)
+ *translation = *match;
+
+ return (0);
+}
+
+/**
* Default bhndb(4) implementation of BUS_GET_DMA_TAG().
*/
static bus_dma_tag_t
bhndb_get_dma_tag(device_t dev, device_t child)
{
- // TODO
- return (NULL);
+ struct bhndb_softc *sc = device_get_softc(dev);
+
+ /*
+ * A bridge may have multiple DMA translation descriptors, each with
+ * their own incompatible restrictions; drivers should in general call
+ * BHND_BUS_GET_DMA_TRANSLATION() to fetch both the best available DMA
+ * translation, and its corresponding DMA tag.
+ *
+ * Child drivers that do not use BHND_BUS_GET_DMA_TRANSLATION() are
+ * responsible for creating their own restricted DMA tag; since we
+ * cannot do this for them in BUS_GET_DMA_TAG(), we simply return the
+ * bridge parent's DMA tag directly;
+ */
+ return (bus_get_dma_tag(sc->parent_dev));
}
static device_method_t bhndb_methods[] = {
@@ -2102,6 +2182,7 @@
DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_bus_generic_get_nvram_var),
DEVMETHOD(bhnd_bus_map_intr, bhndb_bhnd_map_intr),
DEVMETHOD(bhnd_bus_unmap_intr, bhndb_bhnd_unmap_intr),
+ DEVMETHOD(bhnd_bus_get_dma_translation, bhndb_get_dma_translation),
DEVMETHOD(bhnd_bus_get_service_registry,bhndb_get_service_registry),
DEVMETHOD(bhnd_bus_register_provider, bhnd_bus_generic_sr_register_provider),
Index: head/sys/dev/bhnd/bhndb/bhndb_pci.c
===================================================================
--- head/sys/dev/bhnd/bhndb/bhndb_pci.c
+++ head/sys/dev/bhnd/bhndb/bhndb_pci.c
@@ -509,7 +509,7 @@
hint = BHNDB_BUS_GET_CHIPID(parent_dev, dev);
/* Allocate our host resources */
- if ((error = bhndb_alloc_host_resources(parent_dev, cfg, &hr)))
+ if ((error = bhndb_alloc_host_resources(&hr, dev, parent_dev, cfg)))
return (error);
/* Initialize our erom I/O state */
Index: head/sys/dev/bhnd/bhndb/bhndb_pci_hwdata.c
===================================================================
--- head/sys/dev/bhnd/bhndb/bhndb_pci_hwdata.c
+++ head/sys/dev/bhnd/bhndb/bhndb_pci_hwdata.c
@@ -45,6 +45,9 @@
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
+#include <dev/bhnd/cores/pci/bhnd_pcireg.h>
+#include <dev/bhnd/cores/pcie2/bhnd_pcie2_reg.h>
+
#include "bhndbvar.h"
#include "bhndb_pcireg.h"
@@ -100,6 +103,9 @@
},
BHNDB_REGWIN_TABLE_END
},
+
+ /* DMA unsupported under generic configuration */
+ .dma_translations = NULL,
};
@@ -147,6 +153,9 @@
BHNDB_REGWIN_TABLE_END
},
+
+ /* DMA unsupported under generic configuration */
+ .dma_translations = NULL,
};
/**
@@ -319,6 +328,15 @@
},
BHNDB_REGWIN_TABLE_END
},
+
+ .dma_translations = (const struct bhnd_dma_translation[]) {
+ {
+ .base_addr = BHND_PCI_DMA32_TRANSLATION,
+ .addr_mask = ~BHND_PCI_DMA32_MASK,
+ .addrext_mask = BHND_PCI_DMA32_MASK
+ },
+ BHND_DMA_TRANSLATION_TABLE_END
+ }
};
/**
@@ -385,6 +403,15 @@
BHNDB_REGWIN_TABLE_END
},
+
+ .dma_translations = (const struct bhnd_dma_translation[]) {
+ {
+ .base_addr = BHND_PCI_DMA32_TRANSLATION,
+ .addr_mask = ~BHND_PCI_DMA32_MASK,
+ .addrext_mask = BHND_PCI_DMA32_MASK
+ },
+ BHND_DMA_TRANSLATION_TABLE_END
+ }
};
/**
@@ -451,6 +478,20 @@
BHNDB_REGWIN_TABLE_END
},
+
+ .dma_translations = (const struct bhnd_dma_translation[]) {
+ {
+ .base_addr = BHND_PCIE_DMA32_TRANSLATION,
+ .addr_mask = ~BHND_PCIE_DMA32_MASK,
+ .addrext_mask = BHND_PCIE_DMA32_MASK
+ },
+ {
+ .base_addr = BHND_PCIE_DMA64_TRANSLATION,
+ .addr_mask = ~BHND_PCIE_DMA64_MASK,
+ .addrext_mask = 0
+ },
+ BHND_DMA_TRANSLATION_TABLE_END
+ }
};
/**
@@ -520,6 +561,20 @@
BHNDB_REGWIN_TABLE_END
},
+
+ .dma_translations = (const struct bhnd_dma_translation[]) {
+ {
+ .base_addr = BHND_PCIE_DMA32_TRANSLATION,
+ .addr_mask = ~BHND_PCIE_DMA32_MASK,
+ .addrext_mask = BHND_PCIE_DMA32_MASK
+ },
+ {
+ .base_addr = BHND_PCIE_DMA64_TRANSLATION,
+ .addr_mask = ~BHND_PCIE_DMA64_MASK,
+ .addrext_mask = 0
+ },
+ BHND_DMA_TRANSLATION_TABLE_END
+ }
};
/**
@@ -589,4 +644,13 @@
BHNDB_REGWIN_TABLE_END
},
+
+ .dma_translations = (const struct bhnd_dma_translation[]) {
+ {
+ .base_addr = BHND_PCIE2_DMA64_TRANSLATION,
+ .addr_mask = ~BHND_PCIE2_DMA64_MASK,
+ .addrext_mask = 0
+ },
+ BHND_DMA_TRANSLATION_TABLE_END
+ }
};
Index: head/sys/dev/bhnd/bhndb/bhndb_subr.c
===================================================================
--- head/sys/dev/bhnd/bhndb/bhndb_subr.c
+++ head/sys/dev/bhnd/bhndb/bhndb_subr.c
@@ -41,6 +41,10 @@
#include "bhndb_private.h"
#include "bhndbvar.h"
+static int bhndb_dma_tag_create(device_t dev, bus_dma_tag_t parent_dmat,
+ const struct bhnd_dma_translation *translation,
+ bus_dma_tag_t *dmat);
+
/**
* Attach a BHND bridge device to @p parent.
*
@@ -402,7 +406,7 @@
}
/* Allocate host resources */
- error = bhndb_alloc_host_resources(parent_dev, r->cfg, &r->res);
+ error = bhndb_alloc_host_resources(&r->res, dev, parent_dev, r->cfg);
if (error) {
device_printf(r->dev,
"could not allocate host resources on %s: %d\n",
@@ -494,6 +498,65 @@
}
/**
+ * Create a new DMA tag for the given @p translation.
+ *
+ * @param dev The bridge device.
+ * @param parent_dmat The parent DMA tag, or NULL if none.
+ * @param translation The DMA translation for which a DMA tag will
+ * be created.
+ * @param[out] dmat On success, the newly created DMA tag.
+ *
+ * @retval 0 success
+ * @retval non-zero if creating the new DMA tag otherwise fails, a regular
+ * unix error code will be returned.
+ */
+static int
+bhndb_dma_tag_create(device_t dev, bus_dma_tag_t parent_dmat,
+ const struct bhnd_dma_translation *translation, bus_dma_tag_t *dmat)
+{
+ bus_dma_tag_t translation_tag;
+ bhnd_addr_t dt_mask;
+ bus_addr_t boundary;
+ bus_addr_t lowaddr, highaddr;
+ int error;
+
+ highaddr = BUS_SPACE_MAXADDR;
+ boundary = 0;
+
+ /* Determine full addressable mask */
+ dt_mask = (translation->addr_mask | translation->addrext_mask);
+ KASSERT(dt_mask != 0, ("DMA addr_mask invalid: %#jx",
+ (uintmax_t)dt_mask));
+
+ /* (addr_mask|addrext_mask) is our maximum supported address */
+ lowaddr = MIN(dt_mask, BUS_SPACE_MAXADDR);
+
+ /* Do we need to to avoid crossing a DMA translation window boundary? */
+ if (translation->addr_mask < BUS_SPACE_MAXADDR) {
+ /* round down to nearest power of two */
+ boundary = translation->addr_mask & (~1ULL);
+ }
+
+ /* Create our DMA tag */
+ error = bus_dma_tag_create(parent_dmat,
+ 1, /* alignment */
+ boundary, lowaddr, highaddr,
+ NULL, NULL, /* filter, filterarg */
+ BUS_SPACE_MAXSIZE, 0, /* maxsize, nsegments */
+ BUS_SPACE_MAXSIZE, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &translation_tag);
+ if (error) {
+ device_printf(dev, "failed to create bridge DMA tag: %d\n",
+ error);
+ return (error);
+ }
+
+ *dmat = translation_tag;
+ return (0);
+}
+
+/**
* Deallocate the given bridge resource structure and any associated resources.
*
* @param br Resource state to be deallocated.
@@ -571,31 +634,80 @@
* On success, the caller assumes ownership of the allocated host resources,
* which must be freed via bhndb_release_host_resources().
*
- * @param dev The device to be used when allocating resources
- * (e.g. via bus_alloc_resources()).
+ * @param[out] resources On success, the allocated host resources.
+ * @param dev The bridge device.
+ * @param parent_dev The parent device from which host resources
+ * should be allocated (e.g. via
+ * bus_alloc_resources()).
* @param hwcfg The hardware configuration defining the host
* resources to be allocated
- * @param[out] resources On success, the allocated host resources.
*/
int
-bhndb_alloc_host_resources(device_t dev, const struct bhndb_hwcfg *hwcfg,
- struct bhndb_host_resources **resources)
+bhndb_alloc_host_resources(struct bhndb_host_resources **resources,
+ device_t dev, device_t parent_dev, const struct bhndb_hwcfg *hwcfg)
{
- struct bhndb_host_resources *hr;
- size_t nres;
- int error;
+ struct bhndb_host_resources *hr;
+ const struct bhnd_dma_translation *dt;
+ bus_dma_tag_t parent_dmat;
+ size_t nres, ndt;
+ int error;
+ parent_dmat = bus_get_dma_tag(parent_dev);
+
hr = malloc(sizeof(*hr), M_BHND, M_WAITOK);
- hr->owner = dev;
+ hr->owner = parent_dev;
hr->cfg = hwcfg;
hr->resource_specs = NULL;
hr->resources = NULL;
+ hr->dma_tags = NULL;
+ hr->num_dma_tags = 0;
/* Determine our bridge resource count from the hardware config. */
nres = 0;
for (size_t i = 0; hwcfg->resource_specs[i].type != -1; i++)
nres++;
+ /* Determine the total count and validate our DMA translation table. */
+ ndt = 0;
+ for (dt = hwcfg->dma_translations; dt != NULL &&
+ !BHND_DMA_IS_TRANSLATION_TABLE_END(dt); dt++)
+ {
+ /* Validate the defined translation */
+ if ((dt->base_addr & dt->addr_mask) != 0) {
+ device_printf(dev, "invalid DMA translation; base "
+ "address %#jx overlaps address mask %#jx",
+ (uintmax_t)dt->base_addr, (uintmax_t)dt->addr_mask);
+
+ error = EINVAL;
+ goto failed;
+ }
+
+ if ((dt->addrext_mask & dt->addr_mask) != 0) {
+ device_printf(dev, "invalid DMA translation; addrext "
+ "mask %#jx overlaps address mask %#jx",
+ (uintmax_t)dt->addrext_mask,
+ (uintmax_t)dt->addr_mask);
+
+ error = EINVAL;
+ goto failed;
+ }
+
+ /* Increment our entry count */
+ ndt++;
+ }
+
+ /* Allocate our DMA tags */
+ hr->dma_tags = malloc(sizeof(*hr->dma_tags) * ndt, M_BHND,
+ M_WAITOK|M_ZERO);
+ for (size_t i = 0; i < ndt; i++) {
+ error = bhndb_dma_tag_create(dev, parent_dmat,
+ &hwcfg->dma_translations[i], &hr->dma_tags[i]);
+ if (error)
+ goto failed;
+
+ hr->num_dma_tags++;
+ }
+
/* Allocate space for a non-const copy of our resource_spec
* table; this will be updated with the RIDs assigned by
* bus_alloc_resources. */
@@ -617,7 +729,7 @@
hr->resources);
if (error) {
device_printf(dev, "could not allocate bridge resources via "
- "%s: %d\n", device_get_nameunit(dev), error);
+ "%s: %d\n", device_get_nameunit(parent_dev), error);
goto failed;
}
@@ -631,6 +743,12 @@
if (hr->resources != NULL)
free(hr->resources, M_BHND);
+ for (size_t i = 0; i < hr->num_dma_tags; i++)
+ bus_dma_tag_destroy(hr->dma_tags[i]);
+
+ if (hr->dma_tags != NULL)
+ free(hr->dma_tags, M_BHND);
+
free(hr, M_BHND);
return (error);
@@ -646,8 +764,12 @@
{
bus_release_resources(hr->owner, hr->resource_specs, hr->resources);
+ for (size_t i = 0; i < hr->num_dma_tags; i++)
+ bus_dma_tag_destroy(hr->dma_tags[i]);
+
free(hr->resources, M_BHND);
free(hr->resource_specs, M_BHND);
+ free(hr->dma_tags, M_BHND);
free(hr, M_BHND);
}
Index: head/sys/dev/bhnd/bhndb/bhndbvar.h
===================================================================
--- head/sys/dev/bhnd/bhndb/bhndbvar.h
+++ head/sys/dev/bhnd/bhndb/bhndbvar.h
@@ -90,9 +90,11 @@
void bhndb_free_intr_isrc(
struct bhndb_intr_isrc *isrc);
-int bhndb_alloc_host_resources(device_t dev,
- const struct bhndb_hwcfg *hwcfg,
- struct bhndb_host_resources **resources);
+int bhndb_alloc_host_resources(
+ struct bhndb_host_resources **resources,
+ device_t dev, device_t parent_dev,
+ const struct bhndb_hwcfg *hwcfg);
+
void bhndb_release_host_resources(
struct bhndb_host_resources *resources);
struct resource *bhndb_host_resource_for_range(
@@ -161,6 +163,9 @@
const struct bhndb_hwcfg *cfg; /**< bridge hardware configuration */
struct resource_spec *resource_specs; /**< resource specification table */
struct resource **resources; /**< allocated resource table */
+ bus_dma_tag_t *dma_tags; /**< DMA tags for all hwcfg DMA translations, or NULL
+ if DMA is not supported */
+ size_t num_dma_tags; /**< DMA tag count */
};
/**
Index: head/sys/dev/bhnd/cores/pci/bhnd_pcireg.h
===================================================================
--- head/sys/dev/bhnd/cores/pci/bhnd_pcireg.h
+++ head/sys/dev/bhnd/cores/pci/bhnd_pcireg.h
@@ -29,15 +29,15 @@
* PCI/PCIe-Gen1 DMA Constants
*/
-#define BHND_PCI_DMA32_TRANSLATION 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */
-#define BHND_PCI_DMA32_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */
+#define BHND_PCI_DMA32_TRANSLATION 0x40000000 /**< PCI DMA32 address translation (sbtopci2) */
+#define BHND_PCI_DMA32_MASK BHND_PCI_SBTOPCI2_MASK /**< PCI DMA32 translation mask */
-#define BHND_PCIE_DMA32_TRANSLATION BHND_PCI_DMA32_TRANSLATION
-#define BHND_PCIE_DMA32_SZ BHND_PCI_DMA32_SZ
+#define BHND_PCIE_DMA32_TRANSLATION 0x80000000 /**< PCIe-Gen1 DMA32 address translation (sb2pcitranslation2) */
+#define BHND_PCIE_DMA32_MASK BHND_PCIE_SBTOPCI2_MASK /**< PCIe-Gen1 DMA32 translation mask */
-#define BHND_PCIE_DMA64_L32 0x00000000 /**< 64-bit client mode sb2pcitranslation2 (2 ZettaBytes, low 32 bits) */
-#define BHND_PCIE_DMA64_H32 0x80000000 /**< 64-bit client mode sb2pcitranslation2 (2 ZettaBytes, high 32 bits) */
-
+#define BHND_PCIE_DMA64_TRANSLATION _BHND_PCIE_DMA64(TRANSLATION) /**< PCIe-Gen1 DMA64 address translation (sb2pcitranslation2) */
+#define BHND_PCIE_DMA64_MASK _BHND_PCIE_DMA64(MASK) /**< PCIe-Gen1 DMA64 translation mask */
+#define _BHND_PCIE_DMA64(_x) ((uint64_t)BHND_PCIE_DMA32_ ## _x << 32)
/*
* PCI Core Registers
*/
Index: head/sys/dev/bhnd/cores/pcie2/bhnd_pcie2_reg.h
===================================================================
--- head/sys/dev/bhnd/cores/pcie2/bhnd_pcie2_reg.h
+++ head/sys/dev/bhnd/cores/pcie2/bhnd_pcie2_reg.h
@@ -24,6 +24,17 @@
#ifndef _BHND_CORES_PCIE2_BHND_PCIE2_REG_H_
#define _BHND_CORES_PCIE2_BHND_PCIE2_REG_H_
+/*
+ * PCIe-Gen2 DMA Constants
+ */
+
+#define BHND_PCIE2_DMA64_TRANSLATION 0x8000000000000000 /**< PCIe-Gen2 DMA64 address translation */
+#define BHND_PCIE2_DMA64_MASK 0xc000000000000000 /**< PCIe-Gen2 DMA64 translation mask */
+
+/*
+ * PCIe-Gen2 Core Registers
+ */
+
#define BHND_PCIE2_CLK_CONTROL 0x000
#define BHND_PCIE2_RC_PM_CONTROL 0x004
Index: head/sys/mips/broadcom/bhnd_nexus.c
===================================================================
--- head/sys/mips/broadcom/bhnd_nexus.c
+++ head/sys/mips/broadcom/bhnd_nexus.c
@@ -55,6 +55,8 @@
#include <dev/bhnd/bhndvar.h>
#include <dev/bhnd/bhnd_ids.h>
+#include <dev/bhnd/cores/chipc/chipcreg.h>
+
#include "bcm_machdep.h"
#include "bcm_mipsvar.h"
@@ -194,6 +196,44 @@
intr_unmap_irq(irq);
}
+/**
+ * Default bhnd_nexus implementation of BHND_BUS_GET_DMA_TRANSLATION().
+ */
+static int
+bhnd_nexus_get_dma_translation(device_t dev, device_t child,
+ u_int width, uint32_t flags, bus_dma_tag_t *dmat,
+ struct bhnd_dma_translation *translation)
+{
+ struct bcm_platform *bp = bcm_get_platform();
+
+ /* We don't (currently) support any flags */
+ if (flags != 0x0)
+ return (ENOENT);
+
+ KASSERT(width > 0 && width <= BHND_DMA_ADDR_64BIT,
+ ("invalid width %u", width));
+
+ if (width > BHND_DMA_ADDR_32BIT) {
+ /* Backplane must support 64-bit addressing */
+ if (!(bp->cc_caps & CHIPC_CAP_BKPLN64))
+ return (ENOENT);
+ }
+
+ /* No DMA address translation required */
+ if (dmat != NULL)
+ *dmat = bus_get_dma_tag(dev);
+
+ if (translation != NULL) {
+ *translation = (struct bhnd_dma_translation) {
+ .base_addr = 0x0,
+ .addr_mask = BHND_DMA_ADDR_BITMASK(width),
+ .addrext_mask = 0
+ };
+ }
+
+ return (0);
+}
+
static device_method_t bhnd_nexus_methods[] = {
/* bhnd interface */
DEVMETHOD(bhnd_bus_get_service_registry,bhnd_nexus_get_service_registry),
@@ -206,6 +246,7 @@
DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_nexus_is_hw_disabled),
DEVMETHOD(bhnd_bus_get_attach_type, bhnd_nexus_get_attach_type),
DEVMETHOD(bhnd_bus_get_chipid, bhnd_nexus_get_chipid),
+ DEVMETHOD(bhnd_bus_get_dma_translation, bhnd_nexus_get_dma_translation),
DEVMETHOD(bhnd_bus_get_intr_domain, bhnd_bus_generic_get_intr_domain),
DEVMETHOD(bhnd_bus_map_intr, bhnd_nexus_map_intr),
DEVMETHOD(bhnd_bus_unmap_intr, bhnd_nexus_unmap_intr),
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 21, 7:00 AM (14 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31825124
Default Alt Text
D12582.id35571.diff (26 KB)
Attached To
Mode
D12582: bhnd(4): Add support for querying DMA address translation parameters
Attached
Detach File
Event Timeline
Log In to Comment