dmaengine updates for v5.16-rc1

Updates:
  - Another pile of idxd updates
  - pm routines cleanup for at_xdmac driver
  - Correct handling of callback_result for few drivers
  - zynqmp_dma driver updates and descriptor management refinement
  - Hardware handshaking support for dw-axi-dmac
  - Support for remotely powered controllers in Qcom bam dma
  - tegra driver updates
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmGLtLMACgkQfBQHDyUj
 g0dZKA/+P+OiIoQ3SHvEARL1JCIVKB1aWfIq4RIwQLcEInfL+P461csjld0hBAAJ
 oHZxVhE5PGKJ2qgZWyrhBe+5pX1RZm3U5rkNCA/qvEWQPJPukTP2Wvo28uDmCadz
 PjQ/KfX/OPf+uYiKxxPDwgoFeWbNX0hTIjRqxd0/roclcOLvNGbpDj8KEBYvvh0/
 kzpmn3SMoA/ak3Y7e3AUHQGN8hDEtncETzNojkF8KcNwu3LYjgWqd+PPj7VQYJ8c
 NCaen7iPHYS8ZstgPU4bXaET/yuByv9PLm4Mw11R6y8dUdL/BjD9RRM6KL81dZvS
 /dxtBdequpCod+2Uf0/OOlxUsPYaGyJ3M5NSNAx8Iqz7CX4UkiiQyC5Px5PfBkC/
 BSCxP2D3E9BQ7k/uKO0pDXVpQoLiAGKZAPoONApG3/Y/hgwi2VifmoOte1nvzJx8
 6AGngwHbSyUq8E3M2mIRhpO+3sH58f8cRLOqrxSHxWGq2C9yI3oFqh4n7jW1pDUh
 8DEDTV4JtNF5gxuDi9tM6dqJ5cZvdcQ5ITRjXj4CjTMdd4P4D7hJzxR3OyKyUFiQ
 DqtW9UL0vJdufdE04IL29V5p746XkMe++o0Op912kDUIGSH8vuR9GMs9qvMriysw
 6PZ+DOzlMfdkWc654A8W4vcmqY5JF5xOM00SYznGnruUu/RCNh4=
 =eqOs
 -----END PGP SIGNATURE-----

Merge tag 'dmaengine-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine

Pull dmaengine updates from Vinod Koul:
 "A bunch of driver updates, no new driver or controller support this
  time though:

   - Another pile of idxd updates

   - pm routines cleanup for at_xdmac driver

   - Correct handling of callback_result for few drivers

   - zynqmp_dma driver updates and descriptor management refinement

   - Hardware handshaking support for dw-axi-dmac

   - Support for remotely powered controllers in Qcom bam dma

   - tegra driver updates"

* tag 'dmaengine-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (69 commits)
  dmaengine: ti: k3-udma: Set r/tchan or rflow to NULL if request fail
  dmaengine: ti: k3-udma: Set bchan to NULL if a channel request fail
  dmaengine: stm32-dma: avoid 64-bit division in stm32_dma_get_max_width
  dmaengine: fsl-edma: support edma memcpy
  dmaengine: idxd: fix resource leak on dmaengine driver disable
  dmaengine: idxd: cleanup completion record allocation
  dmaengine: zynqmp_dma: Correctly handle descriptor callbacks
  dmaengine: xilinx_dma: Correctly handle cyclic descriptor callbacks
  dmaengine: altera-msgdma: Correctly handle descriptor callbacks
  dmaengine: at_xdmac: fix compilation warning
  dmaengine: dw-axi-dmac: Simplify assignment in dma_chan_pause()
  dmaengine: qcom: bam_dma: Add "powered remotely" mode
  dt-bindings: dmaengine: bam_dma: Add "powered remotely" mode
  dmaengine: sa11x0: Mark PM functions as __maybe_unused
  dmaengine: switch from 'pci_' to 'dma_' API
  dmaengine: ioat: switch from 'pci_' to 'dma_' API
  dmaengine: hsu: switch from 'pci_' to 'dma_' API
  dmaengine: hisi_dma: switch from 'pci_' to 'dma_' API
  dmaengine: dw: switch from 'pci_' to 'dma_' API
  dmaengine: dw-edma-pcie: switch from 'pci_' to 'dma_' API
  ...
This commit is contained in:
Linus Torvalds 2021-11-10 11:47:55 -08:00
commit e68a7d35bb
44 changed files with 490 additions and 330 deletions

View File

@ -15,6 +15,8 @@ Required properties:
the secure world.
- qcom,controlled-remotely : optional, indicates that the bam is controlled by
remote proccessor i.e. execution environment.
- qcom,powered-remotely : optional, indicates that the bam is powered up by
a remote processor but must be initialized by the local processor.
- num-channels : optional, indicates supported number of DMA channels in a
remotely controlled bam.
- qcom,num-ees : optional, indicates supported number of Execution Environments

View File

@ -717,7 +717,7 @@ config XILINX_DMA
config XILINX_ZYNQMP_DMA
tristate "Xilinx ZynqMP DMA Engine"
depends on (ARCH_ZYNQ || MICROBLAZE || ARM64)
depends on ARCH_ZYNQ || MICROBLAZE || ARM64 || COMPILE_TEST
select DMA_ENGINE
help
Enable support for Xilinx ZynqMP DMA controller.

View File

@ -585,16 +585,14 @@ static void msgdma_chan_desc_cleanup(struct msgdma_device *mdev)
struct msgdma_sw_desc *desc, *next;
list_for_each_entry_safe(desc, next, &mdev->done_list, node) {
dma_async_tx_callback callback;
void *callback_param;
struct dmaengine_desc_callback cb;
list_del(&desc->node);
callback = desc->async_tx.callback;
callback_param = desc->async_tx.callback_param;
if (callback) {
dmaengine_desc_get_callback(&desc->async_tx, &cb);
if (dmaengine_desc_callback_valid(&cb)) {
spin_unlock(&mdev->lock);
callback(callback_param);
dmaengine_desc_callback_invoke(&cb, NULL);
spin_lock(&mdev->lock);
}

View File

@ -155,7 +155,7 @@
#define AT_XDMAC_CC_WRIP (0x1 << 23) /* Write in Progress (read only) */
#define AT_XDMAC_CC_WRIP_DONE (0x0 << 23)
#define AT_XDMAC_CC_WRIP_IN_PROGRESS (0x1 << 23)
#define AT_XDMAC_CC_PERID(i) (0x7f & (i) << 24) /* Channel Peripheral Identifier */
#define AT_XDMAC_CC_PERID(i) ((0x7f & (i)) << 24) /* Channel Peripheral Identifier */
#define AT_XDMAC_CDS_MSP 0x2C /* Channel Data Stride Memory Set Pattern */
#define AT_XDMAC_CSUS 0x30 /* Channel Source Microblock Stride */
#define AT_XDMAC_CDUS 0x34 /* Channel Destination Microblock Stride */
@ -1926,8 +1926,31 @@ static void at_xdmac_free_chan_resources(struct dma_chan *chan)
return;
}
#ifdef CONFIG_PM
static int atmel_xdmac_prepare(struct device *dev)
static void at_xdmac_axi_config(struct platform_device *pdev)
{
struct at_xdmac *atxdmac = (struct at_xdmac *)platform_get_drvdata(pdev);
bool dev_m2m = false;
u32 dma_requests;
if (!atxdmac->layout->axi_config)
return; /* Not supported */
if (!of_property_read_u32(pdev->dev.of_node, "dma-requests",
&dma_requests)) {
dev_info(&pdev->dev, "controller in mem2mem mode.\n");
dev_m2m = true;
}
if (dev_m2m) {
at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_M2M);
at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_M2M);
} else {
at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_P2M);
at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_P2M);
}
}
static int __maybe_unused atmel_xdmac_prepare(struct device *dev)
{
struct at_xdmac *atxdmac = dev_get_drvdata(dev);
struct dma_chan *chan, *_chan;
@ -1941,12 +1964,8 @@ static int atmel_xdmac_prepare(struct device *dev)
}
return 0;
}
#else
# define atmel_xdmac_prepare NULL
#endif
#ifdef CONFIG_PM_SLEEP
static int atmel_xdmac_suspend(struct device *dev)
static int __maybe_unused atmel_xdmac_suspend(struct device *dev)
{
struct at_xdmac *atxdmac = dev_get_drvdata(dev);
struct dma_chan *chan, *_chan;
@ -1970,11 +1989,12 @@ static int atmel_xdmac_suspend(struct device *dev)
return 0;
}
static int atmel_xdmac_resume(struct device *dev)
static int __maybe_unused atmel_xdmac_resume(struct device *dev)
{
struct at_xdmac *atxdmac = dev_get_drvdata(dev);
struct at_xdmac_chan *atchan;
struct dma_chan *chan, *_chan;
struct platform_device *pdev = container_of(dev, struct platform_device, dev);
int i;
int ret;
@ -1982,6 +2002,8 @@ static int atmel_xdmac_resume(struct device *dev)
if (ret)
return ret;
at_xdmac_axi_config(pdev);
/* Clear pending interrupts. */
for (i = 0; i < atxdmac->dma.chancnt; i++) {
atchan = &atxdmac->chan[i];
@ -2005,31 +2027,6 @@ static int atmel_xdmac_resume(struct device *dev)
}
return 0;
}
#endif /* CONFIG_PM_SLEEP */
static void at_xdmac_axi_config(struct platform_device *pdev)
{
struct at_xdmac *atxdmac = (struct at_xdmac *)platform_get_drvdata(pdev);
bool dev_m2m = false;
u32 dma_requests;
if (!atxdmac->layout->axi_config)
return; /* Not supported */
if (!of_property_read_u32(pdev->dev.of_node, "dma-requests",
&dma_requests)) {
dev_info(&pdev->dev, "controller in mem2mem mode.\n");
dev_m2m = true;
}
if (dev_m2m) {
at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_M2M);
at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_M2M);
} else {
at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_P2M);
at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_P2M);
}
}
static int at_xdmac_probe(struct platform_device *pdev)
{
@ -2210,7 +2207,7 @@ static int at_xdmac_remove(struct platform_device *pdev)
return 0;
}
static const struct dev_pm_ops atmel_xdmac_dev_pm_ops = {
static const struct dev_pm_ops __maybe_unused atmel_xdmac_dev_pm_ops = {
.prepare = atmel_xdmac_prepare,
SET_LATE_SYSTEM_SLEEP_PM_OPS(atmel_xdmac_suspend, atmel_xdmac_resume)
};
@ -2234,7 +2231,7 @@ static struct platform_driver at_xdmac_driver = {
.driver = {
.name = "at_xdmac",
.of_match_table = of_match_ptr(atmel_xdmac_dt_ids),
.pm = &atmel_xdmac_dev_pm_ops,
.pm = pm_ptr(&atmel_xdmac_dev_pm_ops),
}
};

View File

@ -133,7 +133,7 @@ void bcom_ata_reset_bd(struct bcom_task *tsk)
struct bcom_ata_var *var;
/* Reset all BD */
memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
tsk->index = 0;
tsk->outdex = 0;

View File

@ -95,7 +95,7 @@ bcom_task_alloc(int bd_count, int bd_size, int priv_size)
tsk->bd = bcom_sram_alloc(bd_count * bd_size, 4, &tsk->bd_pa);
if (!tsk->bd)
goto error;
memset(tsk->bd, 0x00, bd_count * bd_size);
memset_io(tsk->bd, 0x00, bd_count * bd_size);
tsk->num_bd = bd_count;
tsk->bd_size = bd_size;
@ -186,16 +186,16 @@ bcom_load_image(int task, u32 *task_image)
inc = bcom_task_inc(task);
/* Clear & copy */
memset(var, 0x00, BCOM_VAR_SIZE);
memset(inc, 0x00, BCOM_INC_SIZE);
memset_io(var, 0x00, BCOM_VAR_SIZE);
memset_io(inc, 0x00, BCOM_INC_SIZE);
desc_src = (u32 *)(hdr + 1);
var_src = desc_src + hdr->desc_size;
inc_src = var_src + hdr->var_size;
memcpy(desc, desc_src, hdr->desc_size * sizeof(u32));
memcpy(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32));
memcpy(inc, inc_src, hdr->inc_size * sizeof(u32));
memcpy_toio(desc, desc_src, hdr->desc_size * sizeof(u32));
memcpy_toio(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32));
memcpy_toio(inc, inc_src, hdr->inc_size * sizeof(u32));
return 0;
}
@ -302,13 +302,13 @@ static int bcom_engine_init(void)
return -ENOMEM;
}
memset(bcom_eng->tdt, 0x00, tdt_size);
memset(bcom_eng->ctx, 0x00, ctx_size);
memset(bcom_eng->var, 0x00, var_size);
memset(bcom_eng->fdt, 0x00, fdt_size);
memset_io(bcom_eng->tdt, 0x00, tdt_size);
memset_io(bcom_eng->ctx, 0x00, ctx_size);
memset_io(bcom_eng->var, 0x00, var_size);
memset_io(bcom_eng->fdt, 0x00, fdt_size);
/* Copy the FDT for the EU#3 */
memcpy(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
memcpy_toio(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
/* Initialize Task base structure */
for (task=0; task<BCOM_MAX_TASKS; task++)

View File

@ -140,7 +140,7 @@ bcom_fec_rx_reset(struct bcom_task *tsk)
tsk->index = 0;
tsk->outdex = 0;
memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
/* Configure some stuff */
bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_RX_BD_PRAGMA);
@ -241,7 +241,7 @@ bcom_fec_tx_reset(struct bcom_task *tsk)
tsk->index = 0;
tsk->outdex = 0;
memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
/* Configure some stuff */
bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_TX_BD_PRAGMA);

View File

@ -142,7 +142,7 @@ bcom_gen_bd_rx_reset(struct bcom_task *tsk)
tsk->index = 0;
tsk->outdex = 0;
memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
/* Configure some stuff */
bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA);
@ -226,7 +226,7 @@ bcom_gen_bd_tx_reset(struct bcom_task *tsk)
tsk->index = 0;
tsk->outdex = 0;
memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
/* Configure some stuff */
bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA);

View File

@ -915,6 +915,7 @@ static int jz4780_dma_probe(struct platform_device *pdev)
dd->dst_addr_widths = JZ_DMA_BUSWIDTHS;
dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
dd->max_sg_burst = JZ_DMA_MAX_DESC;
/*
* Enable DMA controller, mark all channels as not programmable.

View File

@ -695,13 +695,12 @@ static struct dma_chan *find_candidate(struct dma_device *device,
*/
struct dma_chan *dma_get_slave_channel(struct dma_chan *chan)
{
int err = -EBUSY;
/* lock against __dma_request_channel */
mutex_lock(&dma_list_mutex);
if (chan->client_count == 0) {
struct dma_device *device = chan->device;
int err;
dma_cap_set(DMA_PRIVATE, device->cap_mask);
device->privatecnt++;

View File

@ -176,7 +176,7 @@ dmaengine_desc_get_callback_invoke(struct dma_async_tx_descriptor *tx,
static inline bool
dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb)
{
return (cb->callback) ? true : false;
return cb->callback || cb->callback_result;
}
struct dma_chan *dma_get_slave_channel(struct dma_chan *chan);

View File

@ -79,6 +79,32 @@ axi_chan_iowrite64(struct axi_dma_chan *chan, u32 reg, u64 val)
iowrite32(upper_32_bits(val), chan->chan_regs + reg + 4);
}
static inline void axi_chan_config_write(struct axi_dma_chan *chan,
struct axi_dma_chan_config *config)
{
u32 cfg_lo, cfg_hi;
cfg_lo = (config->dst_multblk_type << CH_CFG_L_DST_MULTBLK_TYPE_POS |
config->src_multblk_type << CH_CFG_L_SRC_MULTBLK_TYPE_POS);
if (chan->chip->dw->hdata->reg_map_8_channels) {
cfg_hi = config->tt_fc << CH_CFG_H_TT_FC_POS |
config->hs_sel_src << CH_CFG_H_HS_SEL_SRC_POS |
config->hs_sel_dst << CH_CFG_H_HS_SEL_DST_POS |
config->src_per << CH_CFG_H_SRC_PER_POS |
config->dst_per << CH_CFG_H_DST_PER_POS |
config->prior << CH_CFG_H_PRIORITY_POS;
} else {
cfg_lo |= config->src_per << CH_CFG2_L_SRC_PER_POS |
config->dst_per << CH_CFG2_L_DST_PER_POS;
cfg_hi = config->tt_fc << CH_CFG2_H_TT_FC_POS |
config->hs_sel_src << CH_CFG2_H_HS_SEL_SRC_POS |
config->hs_sel_dst << CH_CFG2_H_HS_SEL_DST_POS |
config->prior << CH_CFG2_H_PRIORITY_POS;
}
axi_chan_iowrite32(chan, CH_CFG_L, cfg_lo);
axi_chan_iowrite32(chan, CH_CFG_H, cfg_hi);
}
static inline void axi_dma_disable(struct axi_dma_chip *chip)
{
u32 val;
@ -154,7 +180,10 @@ static inline void axi_chan_disable(struct axi_dma_chan *chan)
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
val |= BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
if (chan->chip->dw->hdata->reg_map_8_channels)
val |= BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
else
val |= BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
}
@ -163,8 +192,12 @@ static inline void axi_chan_enable(struct axi_dma_chan *chan)
u32 val;
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
if (chan->chip->dw->hdata->reg_map_8_channels)
val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
else
val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
}
@ -179,12 +212,16 @@ static inline bool axi_chan_is_hw_enable(struct axi_dma_chan *chan)
static void axi_dma_hw_init(struct axi_dma_chip *chip)
{
int ret;
u32 i;
for (i = 0; i < chip->dw->hdata->nr_channels; i++) {
axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
axi_chan_disable(&chip->dw->chan[i]);
}
ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));
if (ret)
dev_warn(chip->dev, "Unable to set coherent mask\n");
}
static u32 axi_chan_get_xfer_width(struct axi_dma_chan *chan, dma_addr_t src,
@ -336,7 +373,8 @@ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan,
struct axi_dma_desc *first)
{
u32 priority = chan->chip->dw->hdata->priority[chan->id];
u32 reg, irq_mask;
struct axi_dma_chan_config config;
u32 irq_mask;
u8 lms = 0; /* Select AXI0 master for LLI fetching */
if (unlikely(axi_chan_is_hw_enable(chan))) {
@ -348,36 +386,36 @@ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan,
axi_dma_enable(chan->chip);
reg = (DWAXIDMAC_MBLK_TYPE_LL << CH_CFG_L_DST_MULTBLK_TYPE_POS |
DWAXIDMAC_MBLK_TYPE_LL << CH_CFG_L_SRC_MULTBLK_TYPE_POS);
axi_chan_iowrite32(chan, CH_CFG_L, reg);
reg = (DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC << CH_CFG_H_TT_FC_POS |
priority << CH_CFG_H_PRIORITY_POS |
DWAXIDMAC_HS_SEL_HW << CH_CFG_H_HS_SEL_DST_POS |
DWAXIDMAC_HS_SEL_HW << CH_CFG_H_HS_SEL_SRC_POS);
config.dst_multblk_type = DWAXIDMAC_MBLK_TYPE_LL;
config.src_multblk_type = DWAXIDMAC_MBLK_TYPE_LL;
config.tt_fc = DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC;
config.prior = priority;
config.hs_sel_dst = DWAXIDMAC_HS_SEL_HW;
config.hs_sel_dst = DWAXIDMAC_HS_SEL_HW;
switch (chan->direction) {
case DMA_MEM_TO_DEV:
dw_axi_dma_set_byte_halfword(chan, true);
reg |= (chan->config.device_fc ?
DWAXIDMAC_TT_FC_MEM_TO_PER_DST :
DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC)
<< CH_CFG_H_TT_FC_POS;
config.tt_fc = chan->config.device_fc ?
DWAXIDMAC_TT_FC_MEM_TO_PER_DST :
DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC;
if (chan->chip->apb_regs)
reg |= (chan->id << CH_CFG_H_DST_PER_POS);
config.dst_per = chan->id;
else
config.dst_per = chan->hw_handshake_num;
break;
case DMA_DEV_TO_MEM:
reg |= (chan->config.device_fc ?
DWAXIDMAC_TT_FC_PER_TO_MEM_SRC :
DWAXIDMAC_TT_FC_PER_TO_MEM_DMAC)
<< CH_CFG_H_TT_FC_POS;
config.tt_fc = chan->config.device_fc ?
DWAXIDMAC_TT_FC_PER_TO_MEM_SRC :
DWAXIDMAC_TT_FC_PER_TO_MEM_DMAC;
if (chan->chip->apb_regs)
reg |= (chan->id << CH_CFG_H_SRC_PER_POS);
config.src_per = chan->id;
else
config.src_per = chan->hw_handshake_num;
break;
default:
break;
}
axi_chan_iowrite32(chan, CH_CFG_H, reg);
axi_chan_config_write(chan, &config);
write_chan_llp(chan, first->hw_desc[0].llp | lms);
@ -1120,10 +1158,16 @@ static int dma_chan_pause(struct dma_chan *dchan)
spin_lock_irqsave(&chan->vc.lock, flags);
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT |
BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
if (chan->chip->dw->hdata->reg_map_8_channels) {
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT |
BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
} else {
val = BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT;
axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
}
do {
if (axi_chan_irq_read(chan) & DWAXIDMAC_IRQ_SUSPENDED)
@ -1147,9 +1191,15 @@ static inline void axi_chan_resume(struct axi_dma_chan *chan)
u32 val;
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
val |= (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
if (chan->chip->dw->hdata->reg_map_8_channels) {
val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
val |= (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
} else {
val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
val |= (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
}
chan->is_paused = false;
}
@ -1241,6 +1291,8 @@ static int parse_device_properties(struct axi_dma_chip *chip)
return -EINVAL;
chip->dw->hdata->nr_channels = tmp;
if (tmp <= DMA_REG_MAP_CH_REF)
chip->dw->hdata->reg_map_8_channels = true;
ret = device_property_read_u32(dev, "snps,dma-masters", &tmp);
if (ret)

View File

@ -18,7 +18,7 @@
#include "../virt-dma.h"
#define DMAC_MAX_CHANNELS 8
#define DMAC_MAX_CHANNELS 16
#define DMAC_MAX_MASTERS 2
#define DMAC_MAX_BLK_SIZE 0x200000
@ -30,6 +30,8 @@ struct dw_axi_dma_hcfg {
u32 priority[DMAC_MAX_CHANNELS];
/* maximum supported axi burst length */
u32 axi_rw_burst_len;
/* Register map for DMAX_NUM_CHANNELS <= 8 */
bool reg_map_8_channels;
bool restrict_axi_burst_len;
};
@ -103,6 +105,17 @@ struct axi_dma_desc {
u32 period_len;
};
struct axi_dma_chan_config {
u8 dst_multblk_type;
u8 src_multblk_type;
u8 dst_per;
u8 src_per;
u8 tt_fc;
u8 prior;
u8 hs_sel_dst;
u8 hs_sel_src;
};
static inline struct device *dchan2dev(struct dma_chan *dchan)
{
return &dchan->dev->device;
@ -139,6 +152,8 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
#define DMAC_CHEN 0x018 /* R/W DMAC Channel Enable */
#define DMAC_CHEN_L 0x018 /* R/W DMAC Channel Enable 00-31 */
#define DMAC_CHEN_H 0x01C /* R/W DMAC Channel Enable 32-63 */
#define DMAC_CHSUSPREG 0x020 /* R/W DMAC Channel Suspend */
#define DMAC_CHABORTREG 0x028 /* R/W DMAC Channel Abort */
#define DMAC_INTSTATUS 0x030 /* R DMAC Interrupt Status */
#define DMAC_COMMON_INTCLEAR 0x038 /* W DMAC Interrupt Clear */
#define DMAC_COMMON_INTSTATUS_ENA 0x040 /* R DMAC Interrupt Status Enable */
@ -187,6 +202,7 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
#define DMA_APB_HS_SEL_BIT_SIZE 0x08 /* HW handshake bits per channel */
#define DMA_APB_HS_SEL_MASK 0xFF /* HW handshake select masks */
#define MAX_BLOCK_SIZE 0x1000 /* 1024 blocks * 4 bytes data width */
#define DMA_REG_MAP_CH_REF 0x08 /* Channel count to choose register map */
/* DMAC_CFG */
#define DMAC_EN_POS 0
@ -195,12 +211,20 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
#define INT_EN_POS 1
#define INT_EN_MASK BIT(INT_EN_POS)
/* DMAC_CHEN */
#define DMAC_CHAN_EN_SHIFT 0
#define DMAC_CHAN_EN_WE_SHIFT 8
#define DMAC_CHAN_SUSP_SHIFT 16
#define DMAC_CHAN_SUSP_WE_SHIFT 24
/* DMAC_CHEN2 */
#define DMAC_CHAN_EN2_WE_SHIFT 16
/* DMAC_CHSUSP */
#define DMAC_CHAN_SUSP2_SHIFT 0
#define DMAC_CHAN_SUSP2_WE_SHIFT 16
/* CH_CTL_H */
#define CH_CTL_H_ARLEN_EN BIT(6)
#define CH_CTL_H_ARLEN_POS 7
@ -289,6 +313,15 @@ enum {
DWAXIDMAC_MBLK_TYPE_LL
};
/* CH_CFG2 */
#define CH_CFG2_L_SRC_PER_POS 4
#define CH_CFG2_L_DST_PER_POS 11
#define CH_CFG2_H_TT_FC_POS 0
#define CH_CFG2_H_HS_SEL_SRC_POS 3
#define CH_CFG2_H_HS_SEL_DST_POS 4
#define CH_CFG2_H_PRIORITY_POS 20
/**
* DW AXI DMA channel interrupts
*

View File

@ -249,7 +249,6 @@ static int dw_edma_device_terminate_all(struct dma_chan *dchan)
{
struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
int err = 0;
LIST_HEAD(head);
if (!chan->configured) {
/* Do nothing */

View File

@ -186,27 +186,18 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
pci_set_master(pdev);
/* DMA configuration */
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (!err) {
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
if (err) {
pci_err(pdev, "consistent DMA mask 64 set failed\n");
return err;
}
pci_err(pdev, "DMA mask 64 set failed\n");
return err;
} else {
pci_err(pdev, "DMA mask 64 set failed\n");
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (err) {
pci_err(pdev, "DMA mask 32 set failed\n");
return err;
}
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (err) {
pci_err(pdev, "consistent DMA mask 32 set failed\n");
return err;
}
}
/* Data structure allocation */

View File

@ -32,11 +32,7 @@ static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
pci_set_master(pdev);
pci_try_set_mwi(pdev);
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (ret)
return ret;
ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
return ret;

View File

@ -348,6 +348,7 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
struct fsl_edma_engine *edma = fsl_chan->edma;
struct edma_regs *regs = &fsl_chan->edma->regs;
u32 ch = fsl_chan->vchan.chan.chan_id;
u16 csr = 0;
/*
* TCD parameters are stored in struct fsl_edma_hw_tcd in little
@ -373,6 +374,12 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
edma_writel(edma, (s32)tcd->dlast_sga,
&regs->tcd[ch].dlast_sga);
if (fsl_chan->is_sw) {
csr = le16_to_cpu(tcd->csr);
csr |= EDMA_TCD_CSR_START;
tcd->csr = cpu_to_le16(csr);
}
edma_writew(edma, (s16)tcd->csr, &regs->tcd[ch].csr);
}
@ -587,6 +594,29 @@ struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg(
}
EXPORT_SYMBOL_GPL(fsl_edma_prep_slave_sg);
struct dma_async_tx_descriptor *fsl_edma_prep_memcpy(struct dma_chan *chan,
dma_addr_t dma_dst, dma_addr_t dma_src,
size_t len, unsigned long flags)
{
struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
struct fsl_edma_desc *fsl_desc;
fsl_desc = fsl_edma_alloc_desc(fsl_chan, 1);
if (!fsl_desc)
return NULL;
fsl_desc->iscyclic = false;
fsl_chan->is_sw = true;
/* To match with copy_align and max_seg_size so 1 tcd is enough */
fsl_edma_fill_tcd(fsl_desc->tcd[0].vtcd, dma_src, dma_dst,
EDMA_TCD_ATTR_SSIZE_32BYTE | EDMA_TCD_ATTR_DSIZE_32BYTE,
32, len, 0, 1, 1, 32, 0, true, true, false);
return vchan_tx_prep(&fsl_chan->vchan, &fsl_desc->vdesc, flags);
}
EXPORT_SYMBOL_GPL(fsl_edma_prep_memcpy);
void fsl_edma_xfer_desc(struct fsl_edma_chan *fsl_chan)
{
struct virt_dma_desc *vdesc;
@ -638,12 +668,14 @@ EXPORT_SYMBOL_GPL(fsl_edma_alloc_chan_resources);
void fsl_edma_free_chan_resources(struct dma_chan *chan)
{
struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
struct fsl_edma_engine *edma = fsl_chan->edma;
unsigned long flags;
LIST_HEAD(head);
spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
fsl_edma_disable_request(fsl_chan);
fsl_edma_chan_mux(fsl_chan, 0, false);
if (edma->drvdata->dmamuxs)
fsl_edma_chan_mux(fsl_chan, 0, false);
fsl_chan->edesc = NULL;
vchan_get_all_descriptors(&fsl_chan->vchan, &head);
fsl_edma_unprep_slave_dma(fsl_chan);
@ -652,6 +684,7 @@ void fsl_edma_free_chan_resources(struct dma_chan *chan)
vchan_dma_desc_free_list(&fsl_chan->vchan, &head);
dma_pool_destroy(fsl_chan->tcd_pool);
fsl_chan->tcd_pool = NULL;
fsl_chan->is_sw = false;
}
EXPORT_SYMBOL_GPL(fsl_edma_free_chan_resources);

View File

@ -121,6 +121,7 @@ struct fsl_edma_chan {
struct fsl_edma_desc *edesc;
struct dma_slave_config cfg;
u32 attr;
bool is_sw;
struct dma_pool *tcd_pool;
dma_addr_t dma_dev_addr;
u32 dma_dev_size;
@ -240,6 +241,9 @@ struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flags, void *context);
struct dma_async_tx_descriptor *fsl_edma_prep_memcpy(
struct dma_chan *chan, dma_addr_t dma_dst, dma_addr_t dma_src,
size_t len, unsigned long flags);
void fsl_edma_xfer_desc(struct fsl_edma_chan *fsl_chan);
void fsl_edma_issue_pending(struct dma_chan *chan);
int fsl_edma_alloc_chan_resources(struct dma_chan *chan);

View File

@ -17,6 +17,7 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_dma.h>
#include <linux/dma-mapping.h>
#include "fsl-edma-common.h"
@ -372,6 +373,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
dma_cap_set(DMA_PRIVATE, fsl_edma->dma_dev.cap_mask);
dma_cap_set(DMA_SLAVE, fsl_edma->dma_dev.cap_mask);
dma_cap_set(DMA_CYCLIC, fsl_edma->dma_dev.cap_mask);
dma_cap_set(DMA_MEMCPY, fsl_edma->dma_dev.cap_mask);
fsl_edma->dma_dev.dev = &pdev->dev;
fsl_edma->dma_dev.device_alloc_chan_resources
@ -381,6 +383,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
fsl_edma->dma_dev.device_tx_status = fsl_edma_tx_status;
fsl_edma->dma_dev.device_prep_slave_sg = fsl_edma_prep_slave_sg;
fsl_edma->dma_dev.device_prep_dma_cyclic = fsl_edma_prep_dma_cyclic;
fsl_edma->dma_dev.device_prep_dma_memcpy = fsl_edma_prep_memcpy;
fsl_edma->dma_dev.device_config = fsl_edma_slave_config;
fsl_edma->dma_dev.device_pause = fsl_edma_pause;
fsl_edma->dma_dev.device_resume = fsl_edma_resume;
@ -392,6 +395,10 @@ static int fsl_edma_probe(struct platform_device *pdev)
fsl_edma->dma_dev.dst_addr_widths = FSL_EDMA_BUSWIDTHS;
fsl_edma->dma_dev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
fsl_edma->dma_dev.copy_align = DMAENGINE_ALIGN_32_BYTES;
/* Per worst case 'nbytes = 1' take CITER as the max_seg_size */
dma_set_max_seg_size(fsl_edma->dma_dev.dev, 0x3fff);
platform_set_drvdata(pdev, fsl_edma);
ret = dma_async_device_register(&fsl_edma->dma_dev);

View File

@ -519,11 +519,7 @@ static int hisi_dma_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return ret;
}
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
if (ret)
return ret;
ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (ret)
return ret;

View File

@ -65,11 +65,7 @@ static int hsu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_master(pdev);
pci_try_set_mwi(pdev);
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (ret)
return ret;
ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
return ret;

View File

@ -135,8 +135,6 @@ int idxd_wq_alloc_resources(struct idxd_wq *wq)
struct idxd_device *idxd = wq->idxd;
struct device *dev = &idxd->pdev->dev;
int rc, num_descs, i;
int align;
u64 tmp;
if (wq->type != IDXD_WQT_KERNEL)
return 0;
@ -148,21 +146,13 @@ int idxd_wq_alloc_resources(struct idxd_wq *wq)
if (rc < 0)
return rc;
align = idxd->data->align;
wq->compls_size = num_descs * idxd->data->compl_size + align;
wq->compls_raw = dma_alloc_coherent(dev, wq->compls_size,
&wq->compls_addr_raw, GFP_KERNEL);
if (!wq->compls_raw) {
wq->compls_size = num_descs * idxd->data->compl_size;
wq->compls = dma_alloc_coherent(dev, wq->compls_size, &wq->compls_addr, GFP_KERNEL);
if (!wq->compls) {
rc = -ENOMEM;
goto fail_alloc_compls;
}
/* Adjust alignment */
wq->compls_addr = (wq->compls_addr_raw + (align - 1)) & ~(align - 1);
tmp = (u64)wq->compls_raw;
tmp = (tmp + (align - 1)) & ~(align - 1);
wq->compls = (struct dsa_completion_record *)tmp;
rc = alloc_descs(wq, num_descs);
if (rc < 0)
goto fail_alloc_descs;
@ -191,8 +181,7 @@ int idxd_wq_alloc_resources(struct idxd_wq *wq)
fail_sbitmap_init:
free_descs(wq);
fail_alloc_descs:
dma_free_coherent(dev, wq->compls_size, wq->compls_raw,
wq->compls_addr_raw);
dma_free_coherent(dev, wq->compls_size, wq->compls, wq->compls_addr);
fail_alloc_compls:
free_hw_descs(wq);
return rc;
@ -207,8 +196,7 @@ void idxd_wq_free_resources(struct idxd_wq *wq)
free_hw_descs(wq);
free_descs(wq);
dma_free_coherent(dev, wq->compls_size, wq->compls_raw,
wq->compls_addr_raw);
dma_free_coherent(dev, wq->compls_size, wq->compls, wq->compls_addr);
sbitmap_queue_free(&wq->sbq);
}
@ -427,7 +415,6 @@ void idxd_wq_quiesce(struct idxd_wq *wq)
{
percpu_ref_kill(&wq->wq_active);
wait_for_completion(&wq->wq_dead);
percpu_ref_exit(&wq->wq_active);
}
/* Device control bits */
@ -584,6 +571,8 @@ void idxd_device_reset(struct idxd_device *idxd)
spin_lock(&idxd->dev_lock);
idxd_device_clear_state(idxd);
idxd->state = IDXD_DEV_DISABLED;
idxd_unmask_error_interrupts(idxd);
idxd_msix_perm_setup(idxd);
spin_unlock(&idxd->dev_lock);
}
@ -792,7 +781,7 @@ static int idxd_groups_config_write(struct idxd_device *idxd)
struct device *dev = &idxd->pdev->dev;
/* Setup bandwidth token limit */
if (idxd->token_limit) {
if (idxd->hw.gen_cap.config_en && idxd->token_limit) {
reg.bits = ioread32(idxd->reg_base + IDXD_GENCFG_OFFSET);
reg.token_limit = idxd->token_limit;
iowrite32(reg.bits, idxd->reg_base + IDXD_GENCFG_OFFSET);
@ -1051,8 +1040,6 @@ static int idxd_wq_load_config(struct idxd_wq *wq)
wq->size = wq->wqcfg->wq_size;
wq->threshold = wq->wqcfg->wq_thresh;
if (wq->wqcfg->priv)
wq->type = IDXD_WQT_KERNEL;
/* The driver does not support shared WQ mode in read-only config yet */
if (wq->wqcfg->mode == 0 || wq->wqcfg->pasid_en)

View File

@ -311,6 +311,7 @@ static int idxd_dmaengine_drv_probe(struct idxd_dev *idxd_dev)
err_dma:
idxd_wq_quiesce(wq);
percpu_ref_exit(&wq->wq_active);
err_ref:
idxd_wq_free_resources(wq);
err_res_alloc:
@ -328,9 +329,9 @@ static void idxd_dmaengine_drv_remove(struct idxd_dev *idxd_dev)
mutex_lock(&wq->wq_lock);
idxd_wq_quiesce(wq);
idxd_unregister_dma_channel(wq);
__drv_disable_wq(wq);
idxd_wq_free_resources(wq);
wq->type = IDXD_WQT_NONE;
__drv_disable_wq(wq);
percpu_ref_exit(&wq->wq_active);
mutex_unlock(&wq->wq_lock);
}

View File

@ -187,9 +187,7 @@ struct idxd_wq {
struct dsa_completion_record *compls;
struct iax_completion_record *iax_compls;
};
void *compls_raw;
dma_addr_t compls_addr;
dma_addr_t compls_addr_raw;
int compls_size;
struct idxd_desc **descs;
struct sbitmap_queue sbq;

View File

@ -797,11 +797,19 @@ static void idxd_remove(struct pci_dev *pdev)
int msixcnt = pci_msix_vec_count(pdev);
int i;
dev_dbg(&pdev->dev, "%s called\n", __func__);
idxd_unregister_devices(idxd);
/*
* When ->release() is called for the idxd->conf_dev, it frees all the memory related
* to the idxd context. The driver still needs those bits in order to do the rest of
* the cleanup. However, we do need to unbound the idxd sub-driver. So take a ref
* on the device here to hold off the freeing while allowing the idxd sub-driver
* to unbind.
*/
get_device(idxd_confdev(idxd));
device_unregister(idxd_confdev(idxd));
idxd_shutdown(pdev);
if (device_pasid_enabled(idxd))
idxd_disable_system_pasid(idxd);
idxd_unregister_devices(idxd);
for (i = 0; i < msixcnt; i++) {
irq_entry = &idxd->irq_entries[i];
@ -815,7 +823,7 @@ static void idxd_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
destroy_workqueue(idxd->wq);
perfmon_pmu_remove(idxd);
device_unregister(idxd_confdev(idxd));
put_device(idxd_confdev(idxd));
}
static struct pci_driver idxd_pci_driver = {

View File

@ -63,6 +63,9 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
int i;
bool err = false;
if (cause & IDXD_INTC_HALT_STATE)
goto halt;
if (cause & IDXD_INTC_ERR) {
spin_lock(&idxd->dev_lock);
for (i = 0; i < 4; i++)
@ -121,6 +124,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
if (!err)
return 0;
halt:
gensts.bits = ioread32(idxd->reg_base + IDXD_GENSTATS_OFFSET);
if (gensts.state == IDXD_DEVICE_STATE_HALT) {
idxd->state = IDXD_DEV_HALTED;
@ -134,6 +138,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
queue_work(idxd->wq, &idxd->work);
} else {
spin_lock(&idxd->dev_lock);
idxd->state = IDXD_DEV_HALTED;
idxd_wqs_quiesce(idxd);
idxd_wqs_unmap_portal(idxd);
idxd_device_clear_state(idxd);
@ -221,8 +226,7 @@ static void irq_process_work_list(struct idxd_irq_entry *irq_entry)
list_for_each_entry_safe(desc, n, &irq_entry->work_list, list) {
if (desc->completion->status) {
list_del(&desc->list);
list_add_tail(&desc->list, &flist);
list_move_tail(&desc->list, &flist);
}
}

View File

@ -36,8 +36,7 @@ union gen_cap_reg {
u64 max_batch_shift:4;
u64 max_ims_mult:6;
u64 config_en:1;
u64 max_descs_per_engine:8;
u64 rsvd3:24;
u64 rsvd3:32;
};
u64 bits;
} __packed;
@ -158,6 +157,7 @@ enum idxd_device_reset_type {
#define IDXD_INTC_CMD 0x02
#define IDXD_INTC_OCCUPY 0x04
#define IDXD_INTC_PERFMON_OVFL 0x08
#define IDXD_INTC_HALT_STATE 0x10
#define IDXD_CMD_OFFSET 0xa0
union idxd_command_reg {

View File

@ -741,9 +741,8 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
unsigned long flags;
buf_virt = dma_alloc_coherent(sdma->dev, size, &buf_phys, GFP_KERNEL);
if (!buf_virt) {
if (!buf_virt)
return -ENOMEM;
}
spin_lock_irqsave(&sdma->channel_0_lock, flags);
@ -1227,8 +1226,9 @@ static int sdma_config_channel(struct dma_chan *chan)
if (sdmac->peripheral_type == IMX_DMATYPE_ASRC_SP ||
sdmac->peripheral_type == IMX_DMATYPE_ASRC)
sdma_set_watermarklevel_for_p2p(sdmac);
} else
} else {
__set_bit(sdmac->event_id0, sdmac->event_mask);
}
/* Address */
sdmac->shp_addr = sdmac->per_address;
@ -1241,7 +1241,7 @@ static int sdma_config_channel(struct dma_chan *chan)
}
static int sdma_set_channel_priority(struct sdma_channel *sdmac,
unsigned int priority)
unsigned int priority)
{
struct sdma_engine *sdma = sdmac->sdma;
int channel = sdmac->channel;
@ -1261,7 +1261,7 @@ static int sdma_request_channel0(struct sdma_engine *sdma)
int ret = -EBUSY;
sdma->bd0 = dma_alloc_coherent(sdma->dev, PAGE_SIZE, &sdma->bd0_phys,
GFP_NOWAIT);
GFP_NOWAIT);
if (!sdma->bd0) {
ret = -ENOMEM;
goto out;
@ -1284,7 +1284,7 @@ static int sdma_alloc_bd(struct sdma_desc *desc)
int ret = 0;
desc->bd = dma_alloc_coherent(desc->sdmac->sdma->dev, bd_size,
&desc->bd_phys, GFP_NOWAIT);
&desc->bd_phys, GFP_NOWAIT);
if (!desc->bd) {
ret = -ENOMEM;
goto out;
@ -1757,7 +1757,7 @@ static void sdma_issue_pending(struct dma_chan *chan)
#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V4 46
static void sdma_add_scripts(struct sdma_engine *sdma,
const struct sdma_script_start_addrs *addr)
const struct sdma_script_start_addrs *addr)
{
s32 *addr_arr = (u32 *)addr;
s32 *saddr_arr = (u32 *)sdma->script_addrs;
@ -1840,8 +1840,8 @@ static void sdma_load_firmware(const struct firmware *fw, void *context)
clk_enable(sdma->clk_ahb);
/* download the RAM image for SDMA */
sdma_load_script(sdma, ram_code,
header->ram_code_size,
addr->ram_code_start_addr);
header->ram_code_size,
addr->ram_code_start_addr);
clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb);
@ -1850,8 +1850,8 @@ static void sdma_load_firmware(const struct firmware *fw, void *context)
sdma->fw_loaded = true;
dev_info(sdma->dev, "loaded firmware %d.%d\n",
header->version_major,
header->version_minor);
header->version_major,
header->version_minor);
err_firmware:
release_firmware(fw);
@ -1955,7 +1955,7 @@ static int sdma_init(struct sdma_engine *sdma)
writel_relaxed(0, sdma->regs + SDMA_H_C0PTR);
sdma->channel_control = dma_alloc_coherent(sdma->dev,
MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control) +
MAX_DMA_CHANNELS * sizeof(struct sdma_channel_control) +
sizeof(struct sdma_context_data),
&ccb_phys, GFP_KERNEL);
@ -1965,9 +1965,9 @@ static int sdma_init(struct sdma_engine *sdma)
}
sdma->context = (void *)sdma->channel_control +
MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control);
MAX_DMA_CHANNELS * sizeof(struct sdma_channel_control);
sdma->context_phys = ccb_phys +
MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control);
MAX_DMA_CHANNELS * sizeof(struct sdma_channel_control);
/* disable all channels */
for (i = 0; i < sdma->drvdata->num_events; i++)

View File

@ -1363,15 +1363,9 @@ static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!iomap)
return -ENOMEM;
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (err)
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (err)
return err;
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
if (err)
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (err)
return err;

View File

@ -269,7 +269,7 @@ milbeaut_hdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
if (!md)
return NULL;
md->sgl = kzalloc(sizeof(*sgl) * sg_len, GFP_NOWAIT);
md->sgl = kcalloc(sg_len, sizeof(*sgl), GFP_NOWAIT);
if (!md->sgl) {
kfree(md);
return NULL;

View File

@ -1123,6 +1123,7 @@ static int mmp_pdma_probe(struct platform_device *op)
mmp_pdma_dma_xlate, pdev);
if (ret < 0) {
dev_err(&op->dev, "of_dma_controller_register failed\n");
dma_async_device_unregister(&pdev->device);
return ret;
}
}

View File

@ -563,15 +563,9 @@ static int plx_dma_probe(struct pci_dev *pdev,
if (rc)
return rc;
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(48));
rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48));
if (rc)
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc)
return rc;
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(48));
if (rc)
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (rc)
return rc;

View File

@ -388,6 +388,8 @@ struct bam_device {
/* execution environment ID, from DT */
u32 ee;
bool controlled_remotely;
bool powered_remotely;
u32 active_channels;
const struct reg_offset_data *layout;
@ -415,6 +417,44 @@ static inline void __iomem *bam_addr(struct bam_device *bdev, u32 pipe,
r.ee_mult * bdev->ee;
}
/**
* bam_reset() - reset and initialize BAM registers
* @bdev: bam device
*/
static void bam_reset(struct bam_device *bdev)
{
u32 val;
/* s/w reset bam */
/* after reset all pipes are disabled and idle */
val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL));
val |= BAM_SW_RST;
writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
val &= ~BAM_SW_RST;
writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
/* make sure previous stores are visible before enabling BAM */
wmb();
/* enable bam */
val |= BAM_EN;
writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
/* set descriptor threshhold, start with 4 bytes */
writel_relaxed(DEFAULT_CNT_THRSHLD,
bam_addr(bdev, 0, BAM_DESC_CNT_TRSHLD));
/* Enable default set of h/w workarounds, ie all except BAM_FULL_PIPE */
writel_relaxed(BAM_CNFG_BITS_DEFAULT, bam_addr(bdev, 0, BAM_CNFG_BITS));
/* enable irqs for errors */
writel_relaxed(BAM_ERROR_EN | BAM_HRESP_ERR_EN,
bam_addr(bdev, 0, BAM_IRQ_EN));
/* unmask global bam interrupt */
writel_relaxed(BAM_IRQ_MSK, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE));
}
/**
* bam_reset_channel - Reset individual BAM DMA channel
* @bchan: bam channel
@ -512,6 +552,9 @@ static int bam_alloc_chan(struct dma_chan *chan)
return -ENOMEM;
}
if (bdev->active_channels++ == 0 && bdev->powered_remotely)
bam_reset(bdev);
return 0;
}
@ -565,6 +608,13 @@ static void bam_free_chan(struct dma_chan *chan)
/* disable irq */
writel_relaxed(0, bam_addr(bdev, bchan->id, BAM_P_IRQ_EN));
if (--bdev->active_channels == 0 && bdev->powered_remotely) {
/* s/w reset bam */
val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL));
val |= BAM_SW_RST;
writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
}
err:
pm_runtime_mark_last_busy(bdev->dev);
pm_runtime_put_autosuspend(bdev->dev);
@ -1164,37 +1214,9 @@ static int bam_init(struct bam_device *bdev)
bdev->num_channels = val & BAM_NUM_PIPES_MASK;
}
if (bdev->controlled_remotely)
return 0;
/* s/w reset bam */
/* after reset all pipes are disabled and idle */
val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL));
val |= BAM_SW_RST;
writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
val &= ~BAM_SW_RST;
writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
/* make sure previous stores are visible before enabling BAM */
wmb();
/* enable bam */
val |= BAM_EN;
writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
/* set descriptor threshhold, start with 4 bytes */
writel_relaxed(DEFAULT_CNT_THRSHLD,
bam_addr(bdev, 0, BAM_DESC_CNT_TRSHLD));
/* Enable default set of h/w workarounds, ie all except BAM_FULL_PIPE */
writel_relaxed(BAM_CNFG_BITS_DEFAULT, bam_addr(bdev, 0, BAM_CNFG_BITS));
/* enable irqs for errors */
writel_relaxed(BAM_ERROR_EN | BAM_HRESP_ERR_EN,
bam_addr(bdev, 0, BAM_IRQ_EN));
/* unmask global bam interrupt */
writel_relaxed(BAM_IRQ_MSK, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE));
/* Reset BAM now if fully controlled locally */
if (!bdev->controlled_remotely && !bdev->powered_remotely)
bam_reset(bdev);
return 0;
}
@ -1257,8 +1279,10 @@ static int bam_dma_probe(struct platform_device *pdev)
bdev->controlled_remotely = of_property_read_bool(pdev->dev.of_node,
"qcom,controlled-remotely");
bdev->powered_remotely = of_property_read_bool(pdev->dev.of_node,
"qcom,powered-remotely");
if (bdev->controlled_remotely) {
if (bdev->controlled_remotely || bdev->powered_remotely) {
ret = of_property_read_u32(pdev->dev.of_node, "num-channels",
&bdev->num_channels);
if (ret)
@ -1270,7 +1294,7 @@ static int bam_dma_probe(struct platform_device *pdev)
dev_err(bdev->dev, "num-ees unspecified in dt\n");
}
if (bdev->controlled_remotely)
if (bdev->controlled_remotely || bdev->powered_remotely)
bdev->bamclk = devm_clk_get_optional(bdev->dev, "bam_clk");
else
bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk");

View File

@ -1001,7 +1001,7 @@ static int sa11x0_dma_remove(struct platform_device *pdev)
return 0;
}
static int sa11x0_dma_suspend(struct device *dev)
static __maybe_unused int sa11x0_dma_suspend(struct device *dev)
{
struct sa11x0_dma_dev *d = dev_get_drvdata(dev);
unsigned pch;
@ -1039,7 +1039,7 @@ static int sa11x0_dma_suspend(struct device *dev)
return 0;
}
static int sa11x0_dma_resume(struct device *dev)
static __maybe_unused int sa11x0_dma_resume(struct device *dev)
{
struct sa11x0_dma_dev *d = dev_get_drvdata(dev);
unsigned pch;
@ -1072,12 +1072,7 @@ static int sa11x0_dma_resume(struct device *dev)
}
static const struct dev_pm_ops sa11x0_dma_pm_ops = {
.suspend_noirq = sa11x0_dma_suspend,
.resume_noirq = sa11x0_dma_resume,
.freeze_noirq = sa11x0_dma_suspend,
.thaw_noirq = sa11x0_dma_resume,
.poweroff_noirq = sa11x0_dma_suspend,
.restore_noirq = sa11x0_dma_resume,
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sa11x0_dma_suspend, sa11x0_dma_resume)
};
static struct platform_driver sa11x0_dma_driver = {

View File

@ -1916,7 +1916,7 @@ static int rcar_dmac_probe(struct platform_device *pdev)
ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "runtime PM get sync failed (%d)\n", ret);
return ret;
goto err_pm_disable;
}
ret = rcar_dmac_init(dmac);
@ -1924,7 +1924,7 @@ static int rcar_dmac_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "failed to reset device\n");
goto error;
goto err_pm_disable;
}
/* Initialize engine */
@ -1958,14 +1958,14 @@ static int rcar_dmac_probe(struct platform_device *pdev)
for_each_rcar_dmac_chan(i, dmac, chan) {
ret = rcar_dmac_chan_probe(dmac, chan);
if (ret < 0)
goto error;
goto err_pm_disable;
}
/* Register the DMAC as a DMA provider for DT. */
ret = of_dma_controller_register(pdev->dev.of_node, rcar_dmac_of_xlate,
NULL);
if (ret < 0)
goto error;
goto err_pm_disable;
/*
* Register the DMA engine device.
@ -1974,12 +1974,13 @@ static int rcar_dmac_probe(struct platform_device *pdev)
*/
ret = dma_async_device_register(engine);
if (ret < 0)
goto error;
goto err_dma_free;
return 0;
error:
err_dma_free:
of_dma_controller_free(pdev->dev.of_node);
err_pm_disable:
pm_runtime_disable(&pdev->dev);
return ret;
}

View File

@ -18,6 +18,7 @@
#include <linux/of_dma.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@ -573,7 +574,7 @@ static void rz_dmac_issue_pending(struct dma_chan *chan)
static u8 rz_dmac_ds_to_val_mapping(enum dma_slave_buswidth ds)
{
u8 i;
const enum dma_slave_buswidth ds_lut[] = {
static const enum dma_slave_buswidth ds_lut[] = {
DMA_SLAVE_BUSWIDTH_1_BYTE,
DMA_SLAVE_BUSWIDTH_2_BYTES,
DMA_SLAVE_BUSWIDTH_4_BYTES,
@ -872,6 +873,13 @@ static int rz_dmac_probe(struct platform_device *pdev)
/* Initialize the channels. */
INIT_LIST_HEAD(&dmac->engine.channels);
pm_runtime_enable(&pdev->dev);
ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "pm_runtime_resume_and_get failed\n");
goto err_pm_disable;
}
for (i = 0; i < dmac->n_channels; i++) {
ret = rz_dmac_chan_probe(dmac, &dmac->channels[i], i);
if (ret < 0)
@ -925,6 +933,10 @@ err:
channel->lmdesc.base_dma);
}
pm_runtime_put(&pdev->dev);
err_pm_disable:
pm_runtime_disable(&pdev->dev);
return ret;
}
@ -943,6 +955,8 @@ static int rz_dmac_remove(struct platform_device *pdev)
}
of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(&dmac->engine);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return 0;
}

View File

@ -270,7 +270,6 @@ static enum dma_slave_buswidth stm32_dma_get_max_width(u32 buf_len,
u32 threshold)
{
enum dma_slave_buswidth max_width;
u64 addr = buf_addr;
if (threshold == STM32_DMA_FIFO_THRESHOLD_FULL)
max_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@ -281,7 +280,7 @@ static enum dma_slave_buswidth stm32_dma_get_max_width(u32 buf_len,
max_width > DMA_SLAVE_BUSWIDTH_1_BYTE)
max_width = max_width >> 1;
if (do_div(addr, max_width))
if (buf_addr & (max_width - 1))
max_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
return max_width;
@ -497,6 +496,7 @@ static int stm32_dma_terminate_all(struct dma_chan *c)
spin_lock_irqsave(&chan->vchan.lock, flags);
if (chan->desc) {
dma_cookie_complete(&chan->desc->vdesc.tx);
vchan_terminate_vdesc(&chan->desc->vdesc);
if (chan->busy)
stm32_dma_stop(chan);
@ -753,8 +753,14 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
if (src_bus_width < 0)
return src_bus_width;
/* Set memory burst size */
src_maxburst = STM32_DMA_MAX_BURST;
/*
* Set memory burst size - burst not possible if address is not aligned on
* the address boundary equal to the size of the transfer
*/
if (buf_addr & (buf_len - 1))
src_maxburst = 1;
else
src_maxburst = STM32_DMA_MAX_BURST;
src_best_burst = stm32_dma_get_best_burst(buf_len,
src_maxburst,
fifoth,
@ -803,8 +809,14 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
if (dst_bus_width < 0)
return dst_bus_width;
/* Set memory burst size */
dst_maxburst = STM32_DMA_MAX_BURST;
/*
* Set memory burst size - burst not possible if address is not aligned on
* the address boundary equal to the size of the transfer
*/
if (buf_addr & (buf_len - 1))
dst_maxburst = 1;
else
dst_maxburst = STM32_DMA_MAX_BURST;
dst_best_burst = stm32_dma_get_best_burst(buf_len,
dst_maxburst,
fifoth,

View File

@ -1566,7 +1566,8 @@ static int stm32_mdma_probe(struct platform_device *pdev)
if (count < 0)
count = 0;
dmadev = devm_kzalloc(&pdev->dev, sizeof(*dmadev) + sizeof(u32) * count,
dmadev = devm_kzalloc(&pdev->dev,
struct_size(dmadev, ahb_addr_masks, count),
GFP_KERNEL);
if (!dmadev)
return -ENOMEM;

View File

@ -43,10 +43,8 @@
#define TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS(reqs) (reqs << 4)
#define ADMA_CH_FIFO_CTRL 0x2c
#define TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(val) (((val) & 0xf) << 8)
#define TEGRA210_ADMA_CH_FIFO_CTRL_RXSIZE(val) ((val) & 0xf)
#define TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(val) (((val) & 0x1f) << 8)
#define TEGRA186_ADMA_CH_FIFO_CTRL_RXSIZE(val) ((val) & 0x1f)
#define ADMA_CH_TX_FIFO_SIZE_SHIFT 8
#define ADMA_CH_RX_FIFO_SIZE_SHIFT 0
#define ADMA_CH_LOWER_SRC_ADDR 0x34
#define ADMA_CH_LOWER_TRG_ADDR 0x3c
@ -61,29 +59,26 @@
#define TEGRA_ADMA_BURST_COMPLETE_TIME 20
#define TEGRA210_FIFO_CTRL_DEFAULT (TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(3) | \
TEGRA210_ADMA_CH_FIFO_CTRL_RXSIZE(3))
#define TEGRA186_FIFO_CTRL_DEFAULT (TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(3) | \
TEGRA186_ADMA_CH_FIFO_CTRL_RXSIZE(3))
#define ADMA_CH_REG_FIELD_VAL(val, mask, shift) (((val) & mask) << shift)
struct tegra_adma;
/*
* struct tegra_adma_chip_data - Tegra chip specific data
* @adma_get_burst_config: Function callback used to set DMA burst size.
* @global_reg_offset: Register offset of DMA global register.
* @global_int_clear: Register offset of DMA global interrupt clear.
* @ch_req_tx_shift: Register offset for AHUB transmit channel select.
* @ch_req_rx_shift: Register offset for AHUB receive channel select.
* @ch_base_offset: Register offset of DMA channel registers.
* @has_outstanding_reqs: If DMA channel can have outstanding requests.
* @ch_fifo_ctrl: Default value for channel FIFO CTRL register.
* @ch_req_mask: Mask for Tx or Rx channel select.
* @ch_req_max: Maximum number of Tx or Rx channels available.
* @ch_reg_size: Size of DMA channel register space.
* @nr_channels: Number of DMA channels available.
* @ch_fifo_size_mask: Mask for FIFO size field.
* @sreq_index_offset: Slave channel index offset.
* @has_outstanding_reqs: If DMA channel can have outstanding requests.
*/
struct tegra_adma_chip_data {
unsigned int (*adma_get_burst_config)(unsigned int burst_size);
@ -97,6 +92,8 @@ struct tegra_adma_chip_data {
unsigned int ch_req_max;
unsigned int ch_reg_size;
unsigned int nr_channels;
unsigned int ch_fifo_size_mask;
unsigned int sreq_index_offset;
bool has_outstanding_reqs;
};
@ -560,13 +557,14 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
{
struct tegra_adma_chan_regs *ch_regs = &desc->ch_regs;
const struct tegra_adma_chip_data *cdata = tdc->tdma->cdata;
unsigned int burst_size, adma_dir;
unsigned int burst_size, adma_dir, fifo_size_shift;
if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS)
return -EINVAL;
switch (direction) {
case DMA_MEM_TO_DEV:
fifo_size_shift = ADMA_CH_TX_FIFO_SIZE_SHIFT;
adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB;
burst_size = tdc->sconfig.dst_maxburst;
ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1);
@ -577,6 +575,7 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
break;
case DMA_DEV_TO_MEM:
fifo_size_shift = ADMA_CH_RX_FIFO_SIZE_SHIFT;
adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM;
burst_size = tdc->sconfig.src_maxburst;
ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1);
@ -598,7 +597,27 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
ch_regs->config |= ADMA_CH_CONFIG_WEIGHT_FOR_WRR(1);
if (cdata->has_outstanding_reqs)
ch_regs->config |= TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS(8);
ch_regs->fifo_ctrl = cdata->ch_fifo_ctrl;
/*
* 'sreq_index' represents the current ADMAIF channel number and as per
* HW recommendation its FIFO size should match with the corresponding
* ADMA channel.
*
* ADMA FIFO size is set as per below (based on default ADMAIF channel
* FIFO sizes):
* fifo_size = 0x2 (sreq_index > sreq_index_offset)
* fifo_size = 0x3 (sreq_index <= sreq_index_offset)
*
*/
if (tdc->sreq_index > cdata->sreq_index_offset)
ch_regs->fifo_ctrl =
ADMA_CH_REG_FIELD_VAL(2, cdata->ch_fifo_size_mask,
fifo_size_shift);
else
ch_regs->fifo_ctrl =
ADMA_CH_REG_FIELD_VAL(3, cdata->ch_fifo_size_mask,
fifo_size_shift);
ch_regs->tc = desc->period_len & ADMA_CH_TC_COUNT_MASK;
return tegra_adma_request_alloc(tdc, direction);
@ -782,12 +801,13 @@ static const struct tegra_adma_chip_data tegra210_chip_data = {
.ch_req_tx_shift = 28,
.ch_req_rx_shift = 24,
.ch_base_offset = 0,
.has_outstanding_reqs = false,
.ch_fifo_ctrl = TEGRA210_FIFO_CTRL_DEFAULT,
.ch_req_mask = 0xf,
.ch_req_max = 10,
.ch_reg_size = 0x80,
.nr_channels = 22,
.ch_fifo_size_mask = 0xf,
.sreq_index_offset = 2,
.has_outstanding_reqs = false,
};
static const struct tegra_adma_chip_data tegra186_chip_data = {
@ -797,12 +817,13 @@ static const struct tegra_adma_chip_data tegra186_chip_data = {
.ch_req_tx_shift = 27,
.ch_req_rx_shift = 22,
.ch_base_offset = 0x10000,
.has_outstanding_reqs = true,
.ch_fifo_ctrl = TEGRA186_FIFO_CTRL_DEFAULT,
.ch_req_mask = 0x1f,
.ch_req_max = 20,
.ch_reg_size = 0x100,
.nr_channels = 32,
.ch_fifo_size_mask = 0x1f,
.sreq_index_offset = 4,
.has_outstanding_reqs = true,
};
static const struct of_device_id tegra_adma_of_match[] = {
@ -867,7 +888,7 @@ static int tegra_adma_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
ret = pm_runtime_get_sync(&pdev->dev);
ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0)
goto rpm_disable;
@ -940,7 +961,6 @@ static int tegra_adma_remove(struct platform_device *pdev)
for (i = 0; i < tdma->nr_channels; ++i)
irq_dispose_mapping(tdma->channels[i].irq);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return 0;

View File

@ -1348,6 +1348,7 @@ static int bcdma_get_bchan(struct udma_chan *uc)
{
struct udma_dev *ud = uc->ud;
enum udma_tp_level tpl;
int ret;
if (uc->bchan) {
dev_dbg(ud->dev, "chan%d: already have bchan%d allocated\n",
@ -1365,8 +1366,11 @@ static int bcdma_get_bchan(struct udma_chan *uc)
tpl = ud->bchan_tpl.levels - 1;
uc->bchan = __udma_reserve_bchan(ud, tpl, -1);
if (IS_ERR(uc->bchan))
return PTR_ERR(uc->bchan);
if (IS_ERR(uc->bchan)) {
ret = PTR_ERR(uc->bchan);
uc->bchan = NULL;
return ret;
}
uc->tchan = uc->bchan;
@ -1376,6 +1380,7 @@ static int bcdma_get_bchan(struct udma_chan *uc)
static int udma_get_tchan(struct udma_chan *uc)
{
struct udma_dev *ud = uc->ud;
int ret;
if (uc->tchan) {
dev_dbg(ud->dev, "chan%d: already have tchan%d allocated\n",
@ -1390,8 +1395,11 @@ static int udma_get_tchan(struct udma_chan *uc)
*/
uc->tchan = __udma_reserve_tchan(ud, uc->config.channel_tpl,
uc->config.mapped_channel_id);
if (IS_ERR(uc->tchan))
return PTR_ERR(uc->tchan);
if (IS_ERR(uc->tchan)) {
ret = PTR_ERR(uc->tchan);
uc->tchan = NULL;
return ret;
}
if (ud->tflow_cnt) {
int tflow_id;
@ -1421,6 +1429,7 @@ static int udma_get_tchan(struct udma_chan *uc)
static int udma_get_rchan(struct udma_chan *uc)
{
struct udma_dev *ud = uc->ud;
int ret;
if (uc->rchan) {
dev_dbg(ud->dev, "chan%d: already have rchan%d allocated\n",
@ -1435,8 +1444,13 @@ static int udma_get_rchan(struct udma_chan *uc)
*/
uc->rchan = __udma_reserve_rchan(ud, uc->config.channel_tpl,
uc->config.mapped_channel_id);
if (IS_ERR(uc->rchan)) {
ret = PTR_ERR(uc->rchan);
uc->rchan = NULL;
return ret;
}
return PTR_ERR_OR_ZERO(uc->rchan);
return 0;
}
static int udma_get_chan_pair(struct udma_chan *uc)
@ -1490,6 +1504,7 @@ static int udma_get_chan_pair(struct udma_chan *uc)
static int udma_get_rflow(struct udma_chan *uc, int flow_id)
{
struct udma_dev *ud = uc->ud;
int ret;
if (!uc->rchan) {
dev_err(ud->dev, "chan%d: does not have rchan??\n", uc->id);
@ -1503,8 +1518,13 @@ static int udma_get_rflow(struct udma_chan *uc, int flow_id)
}
uc->rflow = __udma_get_rflow(ud, flow_id);
if (IS_ERR(uc->rflow)) {
ret = PTR_ERR(uc->rflow);
uc->rflow = NULL;
return ret;
}
return PTR_ERR_OR_ZERO(uc->rflow);
return 0;
}
static void bcdma_put_bchan(struct udma_chan *uc)

View File

@ -792,7 +792,7 @@ static void xilinx_vdma_free_tx_segment(struct xilinx_dma_chan *chan,
}
/**
* xilinx_dma_tx_descriptor - Allocate transaction descriptor
* xilinx_dma_alloc_tx_descriptor - Allocate transaction descriptor
* @chan: Driver specific DMA channel
*
* Return: The allocated descriptor on success and NULL on failure.
@ -998,14 +998,12 @@ static void xilinx_dma_chan_handle_cyclic(struct xilinx_dma_chan *chan,
struct xilinx_dma_tx_descriptor *desc,
unsigned long *flags)
{
dma_async_tx_callback callback;
void *callback_param;
struct dmaengine_desc_callback cb;
callback = desc->async_tx.callback;
callback_param = desc->async_tx.callback_param;
if (callback) {
dmaengine_desc_get_callback(&desc->async_tx, &cb);
if (dmaengine_desc_callback_valid(&cb)) {
spin_unlock_irqrestore(&chan->lock, *flags);
callback(callback_param);
dmaengine_desc_callback_invoke(&cb, NULL);
spin_lock_irqsave(&chan->lock, *flags);
}
}
@ -2483,7 +2481,7 @@ static void xilinx_dma_synchronize(struct dma_chan *dchan)
}
/**
* xilinx_dma_channel_set_config - Configure VDMA channel
* xilinx_vdma_channel_set_config - Configure VDMA channel
* Run-time configuration for Axi VDMA, supports:
* . halt the channel
* . configure interrupt coalescing and inter-packet delay threshold

View File

@ -271,9 +271,6 @@ struct xilinx_dpdma_device {
/* -----------------------------------------------------------------------------
* DebugFS
*/
#ifdef CONFIG_DEBUG_FS
#define XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE 32
#define XILINX_DPDMA_DEBUGFS_UINT16_MAX_STR "65535"
@ -299,7 +296,7 @@ struct xilinx_dpdma_debugfs_request {
static void xilinx_dpdma_debugfs_desc_done_irq(struct xilinx_dpdma_chan *chan)
{
if (chan->id == dpdma_debugfs.chan_id)
if (IS_ENABLED(CONFIG_DEBUG_FS) && chan->id == dpdma_debugfs.chan_id)
dpdma_debugfs.xilinx_dpdma_irq_done_count++;
}
@ -462,16 +459,6 @@ static void xilinx_dpdma_debugfs_init(struct xilinx_dpdma_device *xdev)
dev_err(xdev->dev, "Failed to create debugfs testcase file\n");
}
#else
static void xilinx_dpdma_debugfs_init(struct xilinx_dpdma_device *xdev)
{
}
static void xilinx_dpdma_debugfs_desc_done_irq(struct xilinx_dpdma_chan *chan)
{
}
#endif /* CONFIG_DEBUG_FS */
/* -----------------------------------------------------------------------------
* I/O Accessors
*/

View File

@ -6,15 +6,12 @@
*/
#include <linux/bitops.h>
#include <linux/dmapool.h>
#include <linux/dma/xilinx_dma.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_dma.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
#include <linux/clk.h>
@ -603,22 +600,25 @@ static void zynqmp_dma_start_transfer(struct zynqmp_dma_chan *chan)
static void zynqmp_dma_chan_desc_cleanup(struct zynqmp_dma_chan *chan)
{
struct zynqmp_dma_desc_sw *desc, *next;
unsigned long irqflags;
spin_lock_irqsave(&chan->lock, irqflags);
list_for_each_entry_safe(desc, next, &chan->done_list, node) {
dma_async_tx_callback callback;
void *callback_param;
struct dmaengine_desc_callback cb;
callback = desc->async_tx.callback;
callback_param = desc->async_tx.callback_param;
if (callback) {
spin_unlock(&chan->lock);
callback(callback_param);
spin_lock(&chan->lock);
dmaengine_desc_get_callback(&desc->async_tx, &cb);
if (dmaengine_desc_callback_valid(&cb)) {
spin_unlock_irqrestore(&chan->lock, irqflags);
dmaengine_desc_callback_invoke(&cb, NULL);
spin_lock_irqsave(&chan->lock, irqflags);
}
/* Run any dependencies, then free the descriptor */
zynqmp_dma_free_descriptor(chan, desc);
}
spin_unlock_irqrestore(&chan->lock, irqflags);
}
/**
@ -658,9 +658,13 @@ static void zynqmp_dma_issue_pending(struct dma_chan *dchan)
*/
static void zynqmp_dma_free_descriptors(struct zynqmp_dma_chan *chan)
{
unsigned long irqflags;
spin_lock_irqsave(&chan->lock, irqflags);
zynqmp_dma_free_desc_list(chan, &chan->active_list);
zynqmp_dma_free_desc_list(chan, &chan->pending_list);
zynqmp_dma_free_desc_list(chan, &chan->done_list);
spin_unlock_irqrestore(&chan->lock, irqflags);
}
/**
@ -670,11 +674,8 @@ static void zynqmp_dma_free_descriptors(struct zynqmp_dma_chan *chan)
static void zynqmp_dma_free_chan_resources(struct dma_chan *dchan)
{
struct zynqmp_dma_chan *chan = to_chan(dchan);
unsigned long irqflags;
spin_lock_irqsave(&chan->lock, irqflags);
zynqmp_dma_free_descriptors(chan);
spin_unlock_irqrestore(&chan->lock, irqflags);
dma_free_coherent(chan->dev,
(2 * ZYNQMP_DMA_DESC_SIZE(chan) * ZYNQMP_DMA_NUM_DESCS),
chan->desc_pool_v, chan->desc_pool_p);
@ -689,11 +690,16 @@ static void zynqmp_dma_free_chan_resources(struct dma_chan *dchan)
*/
static void zynqmp_dma_reset(struct zynqmp_dma_chan *chan)
{
unsigned long irqflags;
writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS);
spin_lock_irqsave(&chan->lock, irqflags);
zynqmp_dma_complete_descriptor(chan);
spin_unlock_irqrestore(&chan->lock, irqflags);
zynqmp_dma_chan_desc_cleanup(chan);
zynqmp_dma_free_descriptors(chan);
zynqmp_dma_init(chan);
}
@ -749,27 +755,27 @@ static void zynqmp_dma_do_tasklet(struct tasklet_struct *t)
u32 count;
unsigned long irqflags;
spin_lock_irqsave(&chan->lock, irqflags);
if (chan->err) {
zynqmp_dma_reset(chan);
chan->err = false;
goto unlock;
return;
}
spin_lock_irqsave(&chan->lock, irqflags);
count = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT);
while (count) {
zynqmp_dma_complete_descriptor(chan);
zynqmp_dma_chan_desc_cleanup(chan);
count--;
}
if (chan->idle)
zynqmp_dma_start_transfer(chan);
unlock:
spin_unlock_irqrestore(&chan->lock, irqflags);
zynqmp_dma_chan_desc_cleanup(chan);
if (chan->idle) {
spin_lock_irqsave(&chan->lock, irqflags);
zynqmp_dma_start_transfer(chan);
spin_unlock_irqrestore(&chan->lock, irqflags);
}
}
/**
@ -781,12 +787,9 @@ unlock:
static int zynqmp_dma_device_terminate_all(struct dma_chan *dchan)
{
struct zynqmp_dma_chan *chan = to_chan(dchan);
unsigned long irqflags;
spin_lock_irqsave(&chan->lock, irqflags);
writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS);
zynqmp_dma_free_descriptors(chan);
spin_unlock_irqrestore(&chan->lock, irqflags);
return 0;
}
@ -1061,16 +1064,14 @@ static int zynqmp_dma_probe(struct platform_device *pdev)
p->dev = &pdev->dev;
zdev->clk_main = devm_clk_get(&pdev->dev, "clk_main");
if (IS_ERR(zdev->clk_main)) {
dev_err(&pdev->dev, "main clock not found.\n");
return PTR_ERR(zdev->clk_main);
}
if (IS_ERR(zdev->clk_main))
return dev_err_probe(&pdev->dev, PTR_ERR(zdev->clk_main),
"main clock not found.\n");
zdev->clk_apb = devm_clk_get(&pdev->dev, "clk_apb");
if (IS_ERR(zdev->clk_apb)) {
dev_err(&pdev->dev, "apb clock not found.\n");
return PTR_ERR(zdev->clk_apb);
}
if (IS_ERR(zdev->clk_apb))
return dev_err_probe(&pdev->dev, PTR_ERR(zdev->clk_apb),
"apb clock not found.\n");
platform_set_drvdata(pdev, zdev);
pm_runtime_set_autosuspend_delay(zdev->dev, ZDMA_PM_TIMEOUT);
@ -1085,7 +1086,7 @@ static int zynqmp_dma_probe(struct platform_device *pdev)
ret = zynqmp_dma_chan_probe(zdev, pdev);
if (ret) {
dev_err(&pdev->dev, "Probing channel failed\n");
dev_err_probe(&pdev->dev, ret, "Probing channel failed\n");
goto err_disable_pm;
}
@ -1097,7 +1098,7 @@ static int zynqmp_dma_probe(struct platform_device *pdev)
ret = of_dma_controller_register(pdev->dev.of_node,
of_zynqmp_dma_xlate, zdev);
if (ret) {
dev_err(&pdev->dev, "Unable to register DMA to DT\n");
dev_err_probe(&pdev->dev, ret, "Unable to register DMA to DT\n");
dma_async_device_unregister(&zdev->common);
goto free_chan_resources;
}
@ -1105,8 +1106,6 @@ static int zynqmp_dma_probe(struct platform_device *pdev)
pm_runtime_mark_last_busy(zdev->dev);
pm_runtime_put_sync_autosuspend(zdev->dev);
dev_info(&pdev->dev, "ZynqMP DMA driver Probe success\n");
return 0;
free_chan_resources:

View File

@ -944,10 +944,8 @@ struct dma_device {
void (*device_issue_pending)(struct dma_chan *chan);
void (*device_release)(struct dma_device *dev);
/* debugfs support */
#ifdef CONFIG_DEBUG_FS
void (*dbg_summary_show)(struct seq_file *s, struct dma_device *dev);
struct dentry *dbg_dev_root;
#endif
};
static inline int dmaengine_slave_config(struct dma_chan *chan,