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>
This commit is contained in:
committed by
Vinod Koul
parent
7bd903c5ca
commit
a8135d0d79
@@ -606,12 +606,39 @@ enum dmaengine_alignment {
|
||||
DMAENGINE_ALIGN_64_BYTES = 6,
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
Reference in New Issue
Block a user