summaryrefslogtreecommitdiffstats
path: root/include/linux/dmaengine.h
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2015-12-14 22:47:40 +0200
committerVinod Koul <vinod.koul@intel.com>2015-12-18 11:17:26 +0530
commita8135d0d79e9d0ad3a4ff494fceeaae838becf38 (patch)
tree3aba1f9650cf172838575013e74ce905c67418fc /include/linux/dmaengine.h
parent7bd903c5ca47fde5ad52370a47776491813c772e (diff)
downloadtalos-op-linux-a8135d0d79e9d0ad3a4ff494fceeaae838becf38.tar.gz
talos-op-linux-a8135d0d79e9d0ad3a4ff494fceeaae838becf38.zip
dmaengine: core: Introduce new, universal API to request a channel
The two API function can cover most, if not all current APIs used to request a channel. With minimal effort dmaengine drivers, platforms and dmaengine user drivers can be converted to use the two function. struct dma_chan *dma_request_chan_by_mask(const dma_cap_mask_t *mask); To request any channel matching with the requested capabilities, can be used to request channel for memcpy, memset, xor, etc where no hardware synchronization is needed. struct dma_chan *dma_request_chan(struct device *dev, const char *name); To request a slave channel. The dma_request_chan() will try to find the channel via DT, ACPI or in case if the kernel booted in non DT/ACPI mode it will use a filter lookup table and retrieves the needed information from the dma_slave_map provided by the DMA drivers. This legacy mode needs changes in platform code, in dmaengine drivers and finally the dmaengine user drivers can be converted: For each dmaengine driver an array of DMA device, slave and the parameter for the filter function needs to be added: static const struct dma_slave_map da830_edma_map[] = { { "davinci-mcasp.0", "rx", EDMA_FILTER_PARAM(0, 0) }, { "davinci-mcasp.0", "tx", EDMA_FILTER_PARAM(0, 1) }, { "davinci-mcasp.1", "rx", EDMA_FILTER_PARAM(0, 2) }, { "davinci-mcasp.1", "tx", EDMA_FILTER_PARAM(0, 3) }, { "davinci-mcasp.2", "rx", EDMA_FILTER_PARAM(0, 4) }, { "davinci-mcasp.2", "tx", EDMA_FILTER_PARAM(0, 5) }, { "spi_davinci.0", "rx", EDMA_FILTER_PARAM(0, 14) }, { "spi_davinci.0", "tx", EDMA_FILTER_PARAM(0, 15) }, { "da830-mmc.0", "rx", EDMA_FILTER_PARAM(0, 16) }, { "da830-mmc.0", "tx", EDMA_FILTER_PARAM(0, 17) }, { "spi_davinci.1", "rx", EDMA_FILTER_PARAM(0, 18) }, { "spi_davinci.1", "tx", EDMA_FILTER_PARAM(0, 19) }, }; This information is going to be needed by the dmaengine driver, so modification to the platform_data is needed, and the driver map should be added to the pdata of the DMA driver: da8xx_edma0_pdata.slave_map = da830_edma_map; da8xx_edma0_pdata.slavecnt = ARRAY_SIZE(da830_edma_map); The DMA driver then needs to configure the needed device -> filter_fn mapping before it registers with dma_async_device_register() : ecc->dma_slave.filter_map.map = info->slave_map; ecc->dma_slave.filter_map.mapcnt = info->slavecnt; ecc->dma_slave.filter_map.fn = edma_filter_fn; When neither DT or ACPI lookup is available the dma_request_chan() will try to match the requester's device name with the filter_map's list of device names, when a match found it will use the information from the dma_slave_map to get the channel with the dma_get_channel() internal function. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'include/linux/dmaengine.h')
-rw-r--r--include/linux/dmaengine.h51
1 files changed, 44 insertions, 7 deletions
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index c47c68e535e8..d50a6b51a73d 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -607,11 +607,38 @@ enum dmaengine_alignment {
};
/**
+ * struct dma_slave_map - associates slave device and it's slave channel with
+ * parameter to be used by a filter function
+ * @devname: name of the device
+ * @slave: slave channel name
+ * @param: opaque parameter to pass to struct dma_filter.fn
+ */
+struct dma_slave_map {
+ const char *devname;
+ const char *slave;
+ void *param;
+};
+
+/**
+ * struct dma_filter - information for slave device/channel to filter_fn/param
+ * mapping
+ * @fn: filter function callback
+ * @mapcnt: number of slave device/channel in the map
+ * @map: array of channel to filter mapping data
+ */
+struct dma_filter {
+ dma_filter_fn fn;
+ int mapcnt;
+ const struct dma_slave_map *map;
+};
+
+/**
* struct dma_device - info on the entity supplying DMA services
* @chancnt: how many DMA channels are supported
* @privatecnt: how many DMA channels are requested by dma_request_channel
* @channels: the list of struct dma_chan
* @global_node: list_head for global dma_device_list
+ * @filter: information for device/slave to filter function/param mapping
* @cap_mask: one or more dma_capability flags
* @max_xor: maximum number of xor sources, 0 if no capability
* @max_pq: maximum number of PQ sources and PQ-continue capability
@@ -666,6 +693,7 @@ struct dma_device {
unsigned int privatecnt;
struct list_head channels;
struct list_head global_node;
+ struct dma_filter filter;
dma_cap_mask_t cap_mask;
unsigned short max_xor;
unsigned short max_pq;
@@ -1140,9 +1168,11 @@ enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
void dma_issue_pending_all(void);
struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
dma_filter_fn fn, void *fn_param);
-struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
- const char *name);
struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name);
+
+struct dma_chan *dma_request_chan(struct device *dev, const char *name);
+struct dma_chan *dma_request_chan_by_mask(const dma_cap_mask_t *mask);
+
void dma_release_channel(struct dma_chan *chan);
int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps);
#else
@@ -1166,16 +1196,21 @@ static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
{
return NULL;
}
-static inline struct dma_chan *dma_request_slave_channel_reason(
- struct device *dev, const char *name)
-{
- return ERR_PTR(-ENODEV);
-}
static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
const char *name)
{
return NULL;
}
+static inline struct dma_chan *dma_request_chan(struct device *dev,
+ const char *name)
+{
+ return ERR_PTR(-ENODEV);
+}
+static inline struct dma_chan *dma_request_chan_by_mask(
+ const dma_cap_mask_t *mask)
+{
+ return ERR_PTR(-ENODEV);
+}
static inline void dma_release_channel(struct dma_chan *chan)
{
}
@@ -1186,6 +1221,8 @@ static inline int dma_get_slave_caps(struct dma_chan *chan,
}
#endif
+#define dma_request_slave_channel_reason(dev, name) dma_request_chan(dev, name)
+
static inline int dmaengine_desc_set_reuse(struct dma_async_tx_descriptor *tx)
{
struct dma_slave_caps caps;
OpenPOWER on IntegriCloud