aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorLinus Torvalds2016-01-13 10:59:52 -0800
committerLinus Torvalds2016-01-13 10:59:52 -0800
commitd6a322774cb7096ca683fc46ddc9482e02ee6133 (patch)
tree0e5b95d9899eefa5c58f23af8ecadd7e93010586 /include
parent4c257ec37bc365614933c7f0a7fe9b0688dfd1e7 (diff)
parent8b648436eb45c1f561164b24aafd35fb2bee9cfc (diff)
Merge tag 'dmaengine-4.5-rc1' of git://git.infradead.org/users/vkoul/slave-dma
Pull dmaengine updates from Vinod Koul: "This round we have few new features, new driver and updates to few drivers. The new features to dmaengine core are: - Synchronized transfer termination API to terminate the dmaengine transfers in synchronized and async fashion as required by users. We have its user now in ALSA dmaengine lib, img, at_xdma, axi_dmac drivers. - Universal API for channel request and start consolidation of request flows. It's user is ompa-dma driver. - Introduce reuse of descriptors and use in pxa_dma driver Add/Remove: - New STM32 DMA driver - Removal of unused R-Car HPB-DMAC driver Updates: - ti-dma-crossbar updates for supporting eDMA - tegra-apb pm updates - idma64 - mv_xor updates - ste_dma updates" * tag 'dmaengine-4.5-rc1' of git://git.infradead.org/users/vkoul/slave-dma: (54 commits) dmaengine: mv_xor: add suspend/resume support dmaengine: mv_xor: de-duplicate mv_chan_set_mode*() dmaengine: mv_xor: remove mv_xor_chan->current_type field dmaengine: omap-dma: Add support for DMA filter mapping to slave devices dmaengine: edma: Add support for DMA filter mapping to slave devices dmaengine: core: Introduce new, universal API to request a channel dmaengine: core: Move and merge the code paths using private_candidate dmaengine: core: Skip mask matching when it is not provided to private_candidate dmaengine: mdc: Correct terminate_all handling dmaengine: edma: Add probe callback to edma_tptc_driver dmaengine: dw: fix potential memory leak in dw_dma_parse_dt() dmaengine: stm32-dma: Fix unchecked deference of chan->desc dmaengine: sh: Remove unused R-Car HPB-DMAC driver dmaengine: usb-dmac: Document SoC specific compatibility strings ste_dma40: Delete an unnecessary variable initialisation in d40_probe() ste_dma40: Delete another unnecessary check in d40_probe() ste_dma40: Delete an unnecessary check before the function call "kmem_cache_destroy" dmaengine: tegra-apb: Free interrupts before killing tasklets dmaengine: tegra-apb: Update driver to use GFP_NOWAIT dmaengine: tegra-apb: Only save channel state for those in use ...
Diffstat (limited to 'include')
-rw-r--r--include/linux/dca.h5
-rw-r--r--include/linux/dmaengine.h145
-rw-r--r--include/linux/omap-dma.h6
-rw-r--r--include/linux/platform_data/dma-rcar-hpbdma.h103
-rw-r--r--include/linux/platform_data/edma.h7
5 files changed, 154 insertions, 112 deletions
diff --git a/include/linux/dca.h b/include/linux/dca.h
index d27a7a05718d..ad956c2e07a8 100644
--- a/include/linux/dca.h
+++ b/include/linux/dca.h
@@ -34,7 +34,7 @@ void dca_unregister_notify(struct notifier_block *nb);
struct dca_provider {
struct list_head node;
- struct dca_ops *ops;
+ const struct dca_ops *ops;
struct device *cd;
int id;
};
@@ -53,7 +53,8 @@ struct dca_ops {
int (*dev_managed) (struct dca_provider *, struct device *);
};
-struct dca_provider *alloc_dca_provider(struct dca_ops *ops, int priv_size);
+struct dca_provider *alloc_dca_provider(const struct dca_ops *ops,
+ int priv_size);
void free_dca_provider(struct dca_provider *dca);
int register_dca_provider(struct dca_provider *dca, struct device *dev);
void unregister_dca_provider(struct dca_provider *dca, struct device *dev);
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index c47c68e535e8..16a1cad30c33 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
@@ -654,11 +681,14 @@ enum dmaengine_alignment {
* paused. Returns 0 or an error code
* @device_terminate_all: Aborts all transfers on a channel. Returns 0
* or an error code
+ * @device_synchronize: Synchronizes the termination of a transfers to the
+ * current context.
* @device_tx_status: poll for transaction completion, the optional
* txstate parameter can be supplied with a pointer to get a
* struct with auxiliary transfer status information, otherwise the call
* will just return a simple status code
* @device_issue_pending: push pending transactions to hardware
+ * @descriptor_reuse: a submitted transfer can be resubmitted after completion
*/
struct dma_device {
@@ -666,6 +696,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;
@@ -681,6 +712,7 @@ struct dma_device {
u32 src_addr_widths;
u32 dst_addr_widths;
u32 directions;
+ bool descriptor_reuse;
enum dma_residue_granularity residue_granularity;
int (*device_alloc_chan_resources)(struct dma_chan *chan);
@@ -737,6 +769,7 @@ struct dma_device {
int (*device_pause)(struct dma_chan *chan);
int (*device_resume)(struct dma_chan *chan);
int (*device_terminate_all)(struct dma_chan *chan);
+ void (*device_synchronize)(struct dma_chan *chan);
enum dma_status (*device_tx_status)(struct dma_chan *chan,
dma_cookie_t cookie,
@@ -828,6 +861,13 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_sg(
src_sg, src_nents, flags);
}
+/**
+ * dmaengine_terminate_all() - Terminate all active DMA transfers
+ * @chan: The channel for which to terminate the transfers
+ *
+ * This function is DEPRECATED use either dmaengine_terminate_sync() or
+ * dmaengine_terminate_async() instead.
+ */
static inline int dmaengine_terminate_all(struct dma_chan *chan)
{
if (chan->device->device_terminate_all)
@@ -836,6 +876,88 @@ static inline int dmaengine_terminate_all(struct dma_chan *chan)
return -ENOSYS;
}
+/**
+ * dmaengine_terminate_async() - Terminate all active DMA transfers
+ * @chan: The channel for which to terminate the transfers
+ *
+ * Calling this function will terminate all active and pending descriptors
+ * that have previously been submitted to the channel. It is not guaranteed
+ * though that the transfer for the active descriptor has stopped when the
+ * function returns. Furthermore it is possible the complete callback of a
+ * submitted transfer is still running when this function returns.
+ *
+ * dmaengine_synchronize() needs to be called before it is safe to free
+ * any memory that is accessed by previously submitted descriptors or before
+ * freeing any resources accessed from within the completion callback of any
+ * perviously submitted descriptors.
+ *
+ * This function can be called from atomic context as well as from within a
+ * complete callback of a descriptor submitted on the same channel.
+ *
+ * If none of the two conditions above apply consider using
+ * dmaengine_terminate_sync() instead.
+ */
+static inline int dmaengine_terminate_async(struct dma_chan *chan)
+{
+ if (chan->device->device_terminate_all)
+ return chan->device->device_terminate_all(chan);
+
+ return -EINVAL;
+}
+
+/**
+ * dmaengine_synchronize() - Synchronize DMA channel termination
+ * @chan: The channel to synchronize
+ *
+ * Synchronizes to the DMA channel termination to the current context. When this
+ * function returns it is guaranteed that all transfers for previously issued
+ * descriptors have stopped and and it is safe to free the memory assoicated
+ * with them. Furthermore it is guaranteed that all complete callback functions
+ * for a previously submitted descriptor have finished running and it is safe to
+ * free resources accessed from within the complete callbacks.
+ *
+ * The behavior of this function is undefined if dma_async_issue_pending() has
+ * been called between dmaengine_terminate_async() and this function.
+ *
+ * This function must only be called from non-atomic context and must not be
+ * called from within a complete callback of a descriptor submitted on the same
+ * channel.
+ */
+static inline void dmaengine_synchronize(struct dma_chan *chan)
+{
+ might_sleep();
+
+ if (chan->device->device_synchronize)
+ chan->device->device_synchronize(chan);
+}
+
+/**
+ * dmaengine_terminate_sync() - Terminate all active DMA transfers
+ * @chan: The channel for which to terminate the transfers
+ *
+ * Calling this function will terminate all active and pending transfers
+ * that have previously been submitted to the channel. It is similar to
+ * dmaengine_terminate_async() but guarantees that the DMA transfer has actually
+ * stopped and that all complete callbacks have finished running when the
+ * function returns.
+ *
+ * This function must only be called from non-atomic context and must not be
+ * called from within a complete callback of a descriptor submitted on the same
+ * channel.
+ */
+static inline int dmaengine_terminate_sync(struct dma_chan *chan)
+{
+ int ret;
+
+ ret = dmaengine_terminate_async(chan);
+ if (ret)
+ return ret;
+
+ dmaengine_synchronize(chan);
+
+ return 0;
+}
+
static inline int dmaengine_pause(struct dma_chan *chan)
{
if (chan->device->device_pause)
@@ -1140,9 +1262,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 +1290,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 +1315,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;
diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h
index 88fa8af2b937..1d99b61adc65 100644
--- a/include/linux/omap-dma.h
+++ b/include/linux/omap-dma.h
@@ -267,6 +267,9 @@ struct omap_dma_reg {
u8 type;
};
+#define SDMA_FILTER_PARAM(hw_req) ((int[]) { (hw_req) })
+struct dma_slave_map;
+
/* System DMA platform data structure */
struct omap_system_dma_plat_info {
const struct omap_dma_reg *reg_map;
@@ -278,6 +281,9 @@ struct omap_system_dma_plat_info {
void (*clear_dma)(int lch);
void (*dma_write)(u32 val, int reg, int lch);
u32 (*dma_read)(int reg, int lch);
+
+ const struct dma_slave_map *slave_map;
+ int slavecnt;
};
#ifdef CONFIG_ARCH_OMAP2PLUS
diff --git a/include/linux/platform_data/dma-rcar-hpbdma.h b/include/linux/platform_data/dma-rcar-hpbdma.h
deleted file mode 100644
index 648b8ea61a22..000000000000
--- a/include/linux/platform_data/dma-rcar-hpbdma.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2011-2013 Renesas Electronics Corporation
- * Copyright (C) 2013 Cogent Embedded, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- */
-
-#ifndef __DMA_RCAR_HPBDMA_H
-#define __DMA_RCAR_HPBDMA_H
-
-#include <linux/bitops.h>
-#include <linux/types.h>
-
-/* Transmit sizes and respective register values */
-enum {
- XMIT_SZ_8BIT = 0,
- XMIT_SZ_16BIT = 1,
- XMIT_SZ_32BIT = 2,
- XMIT_SZ_MAX
-};
-
-/* DMA control register (DCR) bits */
-#define HPB_DMAE_DCR_DTAMD (1u << 26)
-#define HPB_DMAE_DCR_DTAC (1u << 25)
-#define HPB_DMAE_DCR_DTAU (1u << 24)
-#define HPB_DMAE_DCR_DTAU1 (1u << 23)
-#define HPB_DMAE_DCR_SWMD (1u << 22)
-#define HPB_DMAE_DCR_BTMD (1u << 21)
-#define HPB_DMAE_DCR_PKMD (1u << 20)
-#define HPB_DMAE_DCR_CT (1u << 18)
-#define HPB_DMAE_DCR_ACMD (1u << 17)
-#define HPB_DMAE_DCR_DIP (1u << 16)
-#define HPB_DMAE_DCR_SMDL (1u << 13)
-#define HPB_DMAE_DCR_SPDAM (1u << 12)
-#define HPB_DMAE_DCR_SDRMD_MASK (3u << 10)
-#define HPB_DMAE_DCR_SDRMD_MOD (0u << 10)
-#define HPB_DMAE_DCR_SDRMD_AUTO (1u << 10)
-#define HPB_DMAE_DCR_SDRMD_TIMER (2u << 10)
-#define HPB_DMAE_DCR_SPDS_MASK (3u << 8)
-#define HPB_DMAE_DCR_SPDS_8BIT (0u << 8)
-#define HPB_DMAE_DCR_SPDS_16BIT (1u << 8)
-#define HPB_DMAE_DCR_SPDS_32BIT (2u << 8)
-#define HPB_DMAE_DCR_DMDL (1u << 5)
-#define HPB_DMAE_DCR_DPDAM (1u << 4)
-#define HPB_DMAE_DCR_DDRMD_MASK (3u << 2)
-#define HPB_DMAE_DCR_DDRMD_MOD (0u << 2)
-#define HPB_DMAE_DCR_DDRMD_AUTO (1u << 2)
-#define HPB_DMAE_DCR_DDRMD_TIMER (2u << 2)
-#define HPB_DMAE_DCR_DPDS_MASK (3u << 0)
-#define HPB_DMAE_DCR_DPDS_8BIT (0u << 0)
-#define HPB_DMAE_DCR_DPDS_16BIT (1u << 0)
-#define HPB_DMAE_DCR_DPDS_32BIT (2u << 0)
-
-/* Asynchronous reset register (ASYNCRSTR) bits */
-#define HPB_DMAE_ASYNCRSTR_ASRST41 BIT(10)
-#define HPB_DMAE_ASYNCRSTR_ASRST40 BIT(9)
-#define HPB_DMAE_ASYNCRSTR_ASRST39 BIT(8)
-#define HPB_DMAE_ASYNCRSTR_ASRST27 BIT(7)
-#define HPB_DMAE_ASYNCRSTR_ASRST26 BIT(6)
-#define HPB_DMAE_ASYNCRSTR_ASRST25 BIT(5)
-#define HPB_DMAE_ASYNCRSTR_ASRST24 BIT(4)
-#define HPB_DMAE_ASYNCRSTR_ASRST23 BIT(3)
-#define HPB_DMAE_ASYNCRSTR_ASRST22 BIT(2)
-#define HPB_DMAE_ASYNCRSTR_ASRST21 BIT(1)
-#define HPB_DMAE_ASYNCRSTR_ASRST20 BIT(0)
-
-struct hpb_dmae_slave_config {
- unsigned int id;
- dma_addr_t addr;
- u32 dcr;
- u32 port;
- u32 rstr;
- u32 mdr;
- u32 mdm;
- u32 flags;
-#define HPB_DMAE_SET_ASYNC_RESET BIT(0)
-#define HPB_DMAE_SET_ASYNC_MODE BIT(1)
- u32 dma_ch;
-};
-
-#define HPB_DMAE_CHANNEL(_irq, _s_id) \
-{ \
- .ch_irq = _irq, \
- .s_id = _s_id, \
-}
-
-struct hpb_dmae_channel {
- unsigned int ch_irq;
- unsigned int s_id;
-};
-
-struct hpb_dmae_pdata {
- const struct hpb_dmae_slave_config *slaves;
- int num_slaves;
- const struct hpb_dmae_channel *channels;
- int num_channels;
- const unsigned int ts_shift[XMIT_SZ_MAX];
- int num_hw_channels;
-};
-
-#endif
diff --git a/include/linux/platform_data/edma.h b/include/linux/platform_data/edma.h
index 4299f4ba03bd..0a533f94438f 100644
--- a/include/linux/platform_data/edma.h
+++ b/include/linux/platform_data/edma.h
@@ -53,12 +53,16 @@ enum dma_event_q {
#define EDMA_CTLR(i) ((i) >> 16)
#define EDMA_CHAN_SLOT(i) ((i) & 0xffff)
+#define EDMA_FILTER_PARAM(ctlr, chan) ((int[]) { EDMA_CTLR_CHAN(ctlr, chan) })
+
struct edma_rsv_info {
const s16 (*rsv_chans)[2];
const s16 (*rsv_slots)[2];
};
+struct dma_slave_map;
+
/* platform_data for EDMA driver */
struct edma_soc_info {
/*
@@ -76,6 +80,9 @@ struct edma_soc_info {
s8 (*queue_priority_mapping)[2];
const s16 (*xbar_chans)[2];
+
+ const struct dma_slave_map *slave_map;
+ int slavecnt;
};
#endif