From: Peter Ujfalusi <peter.ujfalusi@ti.com>
To: <vinod.koul@intel.com>, <arnd@arndb.de>, <andy.shevchenko@gmail.com>
Cc: linux-mmc@vger.kernel.org, nsekhar@ti.com,
linux-kernel@vger.kernel.org, linux-spi@vger.kernel.org,
dmaengine@vger.kernel.org, linux-omap@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
Subject: [RFC v02 03/15] dmaengine: core: Introduce new, universal API to request a channel
Date: Mon, 30 Nov 2015 15:45:33 +0200 [thread overview]
Message-ID: <1448891145-10766-4-git-send-email-peter.ujfalusi@ti.com> (raw)
In-Reply-To: <1448891145-10766-1-git-send-email-peter.ujfalusi@ti.com>
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_filter_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 struct dma_filter_map da830_edma_map[] = {
DMA_FILTER_ENTRY("davinci-mcasp.0", "rx", EDMA_CTLR_CHAN(0, 0)),
DMA_FILTER_ENTRY("davinci-mcasp.0", "tx", EDMA_CTLR_CHAN(0, 1)),
DMA_FILTER_ENTRY("davinci-mcasp.1", "rx", EDMA_CTLR_CHAN(0, 2)),
DMA_FILTER_ENTRY("davinci-mcasp.1", "tx", EDMA_CTLR_CHAN(0, 3)),
DMA_FILTER_ENTRY("davinci-mcasp.2", "rx", EDMA_CTLR_CHAN(0, 4)),
DMA_FILTER_ENTRY("davinci-mcasp.2", "tx", EDMA_CTLR_CHAN(0, 5)),
DMA_FILTER_ENTRY("spi_davinci.0", "rx", EDMA_CTLR_CHAN(0, 14)),
DMA_FILTER_ENTRY("spi_davinci.0", "tx", EDMA_CTLR_CHAN(0, 15)),
DMA_FILTER_ENTRY("da830-mmc.0", "rx", EDMA_CTLR_CHAN(0, 16)),
DMA_FILTER_ENTRY("da830-mmc.0", "tx", EDMA_CTLR_CHAN(0, 17)),
DMA_FILTER_ENTRY("spi_davinci.1", "rx", EDMA_CTLR_CHAN(0, 18)),
DMA_FILTER_ENTRY("spi_davinci.1", "tx", EDMA_CTLR_CHAN(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.filter_map = da830_edma_map;
da8xx_edma0_pdata.filtercnt = ARRAY_SIZE(da830_edma_map);
The DMA driver then needs to convigure the needed device -> filter_fn
mapping before it registers with dma_async_device_register() :
if (info->filter_map) {
ecc->dma_slave.filter_map.map = info->filter_map;
ecc->dma_slave.filter_map.mapcnt = info->filtercnt;
ecc->dma_slave.filter_map.filter_fn = edma_filter_for_map;
}
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_filter_map to get the channel with the dma_get_channel() internal
function.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
---
drivers/dma/dmaengine.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/dmaengine.h | 31 +++++++++++++++++++
2 files changed, 107 insertions(+)
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 1249165fb4b2..bd774adff697 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -43,6 +43,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/module.h>
@@ -715,6 +716,81 @@ struct dma_chan *dma_request_slave_channel(struct device *dev,
}
EXPORT_SYMBOL_GPL(dma_request_slave_channel);
+static struct dma_filter_map *dma_filter_match(struct dma_device *device,
+ const char *name,
+ struct device *dev)
+{
+ struct dma_filter_map *map_found = NULL;
+ int i;
+
+ if (!device->filter_map.mapcnt)
+ return NULL;
+
+ for (i = 0; i < device->filter_map.mapcnt; i++) {
+ struct dma_filter_map *map = &device->filter_map.map[i];
+
+ if (!strcmp(map->devname, dev_name(dev)) &&
+ !strcmp(map->slave, name)) {
+ map_found = map;
+ break;
+ }
+ }
+
+ return map_found;
+}
+
+struct dma_chan *dma_request_chan(struct device *dev, const char *name)
+{
+ struct dma_device *device, *_d;
+ struct dma_chan *chan = NULL;
+
+ /* If device-tree is present get slave info from here */
+ if (dev->of_node)
+ chan = of_dma_request_slave_channel(dev->of_node, name);
+
+ /* If device was enumerated by ACPI get slave info from here */
+ if (ACPI_HANDLE(dev) && !chan)
+ chan = acpi_dma_request_slave_chan_by_name(dev, name);
+
+ if (chan)
+ return chan;
+
+ /* Try to find the channel via the DMA filter map(s) */
+ mutex_lock(&dma_list_mutex);
+ list_for_each_entry_safe(device, _d, &dma_device_list, global_node) {
+ struct dma_filter_map *map = dma_filter_match(device, name,
+ dev);
+
+ if (!map)
+ continue;
+
+ chan = dma_get_channel(device, NULL,
+ device->filter_map.filter_fn,
+ map->param);
+ if (!IS_ERR(chan))
+ break;
+ }
+ mutex_unlock(&dma_list_mutex);
+
+ return chan ? chan : ERR_PTR(-EPROBE_DEFER);
+}
+EXPORT_SYMBOL_GPL(dma_request_chan);
+
+struct dma_chan *dma_request_chan_by_mask(const dma_cap_mask_t *mask)
+{
+ struct dma_chan *chan;
+
+ if (!mask)
+ return ERR_PTR(-ENODEV);
+
+ chan = __dma_request_channel(mask, NULL, NULL);
+ if (!chan)
+ chan = ERR_PTR(-ENODEV);
+
+ return chan;
+}
+EXPORT_SYMBOL_GPL(dma_request_chan_by_mask);
+
void dma_release_channel(struct dma_chan *chan)
{
mutex_lock(&dma_list_mutex);
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index a2b7c2071cf4..f7b06ff982c8 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -606,6 +606,24 @@ enum dmaengine_alignment {
DMAENGINE_ALIGN_64_BYTES = 6,
};
+struct dma_filter_map {
+ char *devname;
+ char *slave;
+ void *param;
+};
+#define DMA_FILTER_ENTRY(_devname, _slave, _param) \
+ { \
+ .devname = _devname, \
+ .slave = _slave, \
+ .param = (void*)_param, \
+ }
+
+struct dma_filter {
+ dma_filter_fn filter_fn;
+ int mapcnt;
+ struct dma_filter_map *map;
+};
+
/**
* struct dma_device - info on the entity supplying DMA services
* @chancnt: how many DMA channels are supported
@@ -669,6 +687,7 @@ struct dma_device {
unsigned int privatecnt;
struct list_head channels;
struct list_head global_node;
+ struct dma_filter filter_map;
dma_cap_mask_t cap_mask;
unsigned short max_xor;
unsigned short max_pq;
@@ -1235,6 +1254,10 @@ struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
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
@@ -1268,6 +1291,14 @@ static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
{
return NULL;
}
+static inline struct dma_chan *dma_request_chan(struct device *dev)
+{
+ 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)
{
}
--
2.6.3
next prev parent reply other threads:[~2015-11-30 13:45 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-30 13:45 [RFC v02 00/15] dmaengine: New 'universal' API for requesting channel Peter Ujfalusi
2015-11-30 13:45 ` [RFC v02 01/15] dmaengine: core: Allow NULL mask pointer in __dma_device_satisfies_mask() Peter Ujfalusi
[not found] ` <1448891145-10766-2-git-send-email-peter.ujfalusi-l0cyMroinI0@public.gmane.org>
2015-11-30 14:35 ` Andy Shevchenko
2015-12-01 9:47 ` Peter Ujfalusi
2015-12-01 12:58 ` Andy Shevchenko
2015-12-01 17:06 ` Vinod Koul
2015-11-30 13:45 ` [RFC v02 02/15] dmaengine: core: Move and merge the code paths using private_candidate Peter Ujfalusi
2015-11-30 14:42 ` Andy Shevchenko
2015-12-01 8:41 ` Peter Ujfalusi
2015-11-30 13:45 ` Peter Ujfalusi [this message]
[not found] ` <1448891145-10766-4-git-send-email-peter.ujfalusi-l0cyMroinI0@public.gmane.org>
2015-11-30 14:09 ` [RFC v02 03/15] dmaengine: core: Introduce new, universal API to request a channel Arnd Bergmann
2015-12-01 9:48 ` Peter Ujfalusi
2015-11-30 14:51 ` Andy Shevchenko
2015-12-01 9:56 ` Peter Ujfalusi
2015-12-01 10:07 ` Andy Shevchenko
2015-11-30 15:51 ` Tony Lindgren
2015-12-01 8:13 ` Peter Ujfalusi
2015-12-01 17:00 ` Tony Lindgren
[not found] ` <20151201170031.GT23396-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
2015-12-02 10:00 ` Peter Ujfalusi
[not found] ` <565EC14A.6020502-l0cyMroinI0@public.gmane.org>
2015-12-02 15:00 ` Tony Lindgren
2015-11-30 13:45 ` [RFC v02 04/15] dmaengine: edma: Add support for DMA filter mapping to slave devices Peter Ujfalusi
2015-11-30 14:11 ` Arnd Bergmann
2015-12-01 9:58 ` Peter Ujfalusi
2015-12-01 10:14 ` Arnd Bergmann
2015-12-01 17:22 ` Vinod Koul
2015-12-01 20:20 ` Arnd Bergmann
2015-12-02 4:37 ` Vinod Koul
2015-12-02 10:02 ` Peter Ujfalusi
2015-11-30 13:45 ` [RFC v02 05/15] ARM: davinci: devices-da8xx: Add dma_filter_map to edma Peter Ujfalusi
2015-11-30 13:45 ` [RFC v02 06/15] ARM: davinci: dm355: " Peter Ujfalusi
2015-11-30 13:45 ` [RFC v02 07/15] ARM: davinci: dm365: " Peter Ujfalusi
2015-11-30 13:45 ` [RFC v02 08/15] ARM: davinci: dm644x: " Peter Ujfalusi
2015-11-30 13:45 ` [RFC v02 09/15] ARM: davinci: dm646x: " Peter Ujfalusi
2015-11-30 13:45 ` [RFC v02 10/15] mmc: davinci_mmc: Use dma_request_chan() to requesting DMA channel Peter Ujfalusi
2015-11-30 13:45 ` [RFC v02 11/15] spi: davinci: " Peter Ujfalusi
2016-05-02 11:04 ` Applied "spi: davinci: Use dma_request_chan() for requesting DMA channel" to the spi tree Mark Brown
2015-11-30 13:45 ` [RFC v02 12/15] ARM: davinci: devices-da8xx: Remove DMA resources for MMC and SPI Peter Ujfalusi
2015-11-30 13:45 ` [RFC v02 13/15] ARM: davinci: devices: Remove DMA resources for MMC Peter Ujfalusi
2015-11-30 13:45 ` [RFC v02 14/15] ARM: davinci: dm355: Remove DMA resources for SPI Peter Ujfalusi
2015-11-30 13:45 ` [RFC v02 15/15] ARM: davinci: dm365: " Peter Ujfalusi
2015-11-30 14:18 ` [RFC v02 00/15] dmaengine: New 'universal' API for requesting channel Arnd Bergmann
2015-12-01 10:12 ` Peter Ujfalusi
[not found] ` <565D729F.2000104-l0cyMroinI0@public.gmane.org>
2015-12-01 10:15 ` Arnd Bergmann
2015-11-30 14:32 ` Andy Shevchenko
2015-12-01 13:45 ` Peter Ujfalusi
2015-12-01 14:24 ` Arnd Bergmann
2015-12-02 10:51 ` Peter Ujfalusi
[not found] ` <565ECD3F.3070500-l0cyMroinI0@public.gmane.org>
2015-12-02 13:38 ` Arnd Bergmann
[not found] ` <1448891145-10766-1-git-send-email-peter.ujfalusi-l0cyMroinI0@public.gmane.org>
2015-12-01 16:59 ` Vinod Koul
2015-12-01 20:17 ` Arnd Bergmann
2015-12-02 4:52 ` Vinod Koul
2015-12-02 8:23 ` Arnd Bergmann
2015-12-02 12:29 ` Peter Ujfalusi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1448891145-10766-4-git-send-email-peter.ujfalusi@ti.com \
--to=peter.ujfalusi@ti.com \
--cc=andy.shevchenko@gmail.com \
--cc=arnd@arndb.de \
--cc=dmaengine@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mmc@vger.kernel.org \
--cc=linux-omap@vger.kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=nsekhar@ti.com \
--cc=vinod.koul@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).