Skip to content

Commit d57dd2d

Browse files
committed
Merge tag 'dmaengine-fix2-6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine
Pull dmaengine fixes from Vinod Koul: - dw-edma fixes to improve driver and remote HDMA setup - fsl-edma fixes for SoC hange, irq init and byte calculations and sparse fixes - idxd: safe user copy of completion record fix - ptdma: consistent DMA mask fix * tag 'dmaengine-fix2-6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: dmaengine: ptdma: use consistent DMA masks dmaengine: fsl-qdma: add __iomem and struct in union to fix sparse warning dmaengine: idxd: Ensure safe user copy of completion record dmaengine: fsl-edma: correct max_segment_size setting dmaengine: idxd: Remove shadow Event Log head stored in idxd dmaengine: fsl-edma: correct calculation of 'nbytes' in multi-fifo scenario dmaengine: fsl-qdma: init irq after reg initialization dmaengine: fsl-qdma: fix SoC may hang on 16 byte unaligned read dmaengine: dw-edma: eDMA: Add sync read before starting the DMA transfer in remote setup dmaengine: dw-edma: HDMA: Add sync read before starting the DMA transfer in remote setup dmaengine: dw-edma: Add HDMA remote interrupt configuration dmaengine: dw-edma: HDMA_V0_REMOTEL_STOP_INT_EN typo fix dmaengine: dw-edma: Fix wrong interrupt bit set for HDMA dmaengine: dw-edma: Fix the ch_count hdma callback
2 parents e4f7900 + df2515a commit d57dd2d

File tree

13 files changed

+85
-47
lines changed

13 files changed

+85
-47
lines changed

drivers/dma/dw-edma/dw-edma-v0-core.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,20 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
346346
dw_edma_v0_write_ll_link(chunk, i, control, chunk->ll_region.paddr);
347347
}
348348

349+
static void dw_edma_v0_sync_ll_data(struct dw_edma_chunk *chunk)
350+
{
351+
/*
352+
* In case of remote eDMA engine setup, the DW PCIe RP/EP internal
353+
* configuration registers and application memory are normally accessed
354+
* over different buses. Ensure LL-data reaches the memory before the
355+
* doorbell register is toggled by issuing the dummy-read from the remote
356+
* LL memory in a hope that the MRd TLP will return only after the
357+
* last MWr TLP is completed
358+
*/
359+
if (!(chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL))
360+
readl(chunk->ll_region.vaddr.io);
361+
}
362+
349363
static void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
350364
{
351365
struct dw_edma_chan *chan = chunk->chan;
@@ -412,6 +426,9 @@ static void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
412426
SET_CH_32(dw, chan->dir, chan->id, llp.msb,
413427
upper_32_bits(chunk->ll_region.paddr));
414428
}
429+
430+
dw_edma_v0_sync_ll_data(chunk);
431+
415432
/* Doorbell */
416433
SET_RW_32(dw, chan->dir, doorbell,
417434
FIELD_PREP(EDMA_V0_DOORBELL_CH_MASK, chan->id));

drivers/dma/dw-edma/dw-hdma-v0-core.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,12 @@ static void dw_hdma_v0_core_off(struct dw_edma *dw)
6565

6666
static u16 dw_hdma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
6767
{
68-
u32 num_ch = 0;
69-
int id;
70-
71-
for (id = 0; id < HDMA_V0_MAX_NR_CH; id++) {
72-
if (GET_CH_32(dw, id, dir, ch_en) & BIT(0))
73-
num_ch++;
74-
}
75-
76-
if (num_ch > HDMA_V0_MAX_NR_CH)
77-
num_ch = HDMA_V0_MAX_NR_CH;
78-
79-
return (u16)num_ch;
68+
/*
69+
* The HDMA IP have no way to know the number of hardware channels
70+
* available, we set it to maximum channels and let the platform
71+
* set the right number of channels.
72+
*/
73+
return HDMA_V0_MAX_NR_CH;
8074
}
8175

8276
static enum dma_status dw_hdma_v0_core_ch_status(struct dw_edma_chan *chan)
@@ -228,6 +222,20 @@ static void dw_hdma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
228222
dw_hdma_v0_write_ll_link(chunk, i, control, chunk->ll_region.paddr);
229223
}
230224

225+
static void dw_hdma_v0_sync_ll_data(struct dw_edma_chunk *chunk)
226+
{
227+
/*
228+
* In case of remote HDMA engine setup, the DW PCIe RP/EP internal
229+
* configuration registers and application memory are normally accessed
230+
* over different buses. Ensure LL-data reaches the memory before the
231+
* doorbell register is toggled by issuing the dummy-read from the remote
232+
* LL memory in a hope that the MRd TLP will return only after the
233+
* last MWr TLP is completed
234+
*/
235+
if (!(chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL))
236+
readl(chunk->ll_region.vaddr.io);
237+
}
238+
231239
static void dw_hdma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
232240
{
233241
struct dw_edma_chan *chan = chunk->chan;
@@ -242,7 +250,9 @@ static void dw_hdma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
242250
/* Interrupt enable&unmask - done, abort */
243251
tmp = GET_CH_32(dw, chan->dir, chan->id, int_setup) |
244252
HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK |
245-
HDMA_V0_LOCAL_STOP_INT_EN | HDMA_V0_LOCAL_STOP_INT_EN;
253+
HDMA_V0_LOCAL_STOP_INT_EN | HDMA_V0_LOCAL_ABORT_INT_EN;
254+
if (!(dw->chip->flags & DW_EDMA_CHIP_LOCAL))
255+
tmp |= HDMA_V0_REMOTE_STOP_INT_EN | HDMA_V0_REMOTE_ABORT_INT_EN;
246256
SET_CH_32(dw, chan->dir, chan->id, int_setup, tmp);
247257
/* Channel control */
248258
SET_CH_32(dw, chan->dir, chan->id, control1, HDMA_V0_LINKLIST_EN);
@@ -256,6 +266,9 @@ static void dw_hdma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
256266
/* Set consumer cycle */
257267
SET_CH_32(dw, chan->dir, chan->id, cycle_sync,
258268
HDMA_V0_CONSUMER_CYCLE_STAT | HDMA_V0_CONSUMER_CYCLE_BIT);
269+
270+
dw_hdma_v0_sync_ll_data(chunk);
271+
259272
/* Doorbell */
260273
SET_CH_32(dw, chan->dir, chan->id, doorbell, HDMA_V0_DOORBELL_START);
261274
}

drivers/dma/dw-edma/dw-hdma-v0-regs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#define HDMA_V0_LOCAL_ABORT_INT_EN BIT(6)
1616
#define HDMA_V0_REMOTE_ABORT_INT_EN BIT(5)
1717
#define HDMA_V0_LOCAL_STOP_INT_EN BIT(4)
18-
#define HDMA_V0_REMOTEL_STOP_INT_EN BIT(3)
18+
#define HDMA_V0_REMOTE_STOP_INT_EN BIT(3)
1919
#define HDMA_V0_ABORT_INT_MASK BIT(2)
2020
#define HDMA_V0_STOP_INT_MASK BIT(0)
2121
#define HDMA_V0_LINKLIST_EN BIT(0)

drivers/dma/fsl-edma-common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ void fsl_edma_fill_tcd(struct fsl_edma_chan *fsl_chan,
503503
if (fsl_chan->is_multi_fifo) {
504504
/* set mloff to support multiple fifo */
505505
burst = cfg->direction == DMA_DEV_TO_MEM ?
506-
cfg->src_addr_width : cfg->dst_addr_width;
506+
cfg->src_maxburst : cfg->dst_maxburst;
507507
nbytes |= EDMA_V3_TCD_NBYTES_MLOFF(-(burst * 4));
508508
/* enable DMLOE/SMLOE */
509509
if (cfg->direction == DMA_MEM_TO_DEV) {

drivers/dma/fsl-edma-common.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@
3030
#define EDMA_TCD_ATTR_SSIZE(x) (((x) & GENMASK(2, 0)) << 8)
3131
#define EDMA_TCD_ATTR_SMOD(x) (((x) & GENMASK(4, 0)) << 11)
3232

33-
#define EDMA_TCD_CITER_CITER(x) ((x) & GENMASK(14, 0))
34-
#define EDMA_TCD_BITER_BITER(x) ((x) & GENMASK(14, 0))
33+
#define EDMA_TCD_ITER_MASK GENMASK(14, 0)
34+
#define EDMA_TCD_CITER_CITER(x) ((x) & EDMA_TCD_ITER_MASK)
35+
#define EDMA_TCD_BITER_BITER(x) ((x) & EDMA_TCD_ITER_MASK)
3536

3637
#define EDMA_TCD_CSR_START BIT(0)
3738
#define EDMA_TCD_CSR_INT_MAJOR BIT(1)

drivers/dma/fsl-edma-main.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111

1212
#include <dt-bindings/dma/fsl-edma.h>
13+
#include <linux/bitfield.h>
1314
#include <linux/module.h>
1415
#include <linux/interrupt.h>
1516
#include <linux/clk.h>
@@ -582,7 +583,8 @@ static int fsl_edma_probe(struct platform_device *pdev)
582583
DMAENGINE_ALIGN_32_BYTES;
583584

584585
/* Per worst case 'nbytes = 1' take CITER as the max_seg_size */
585-
dma_set_max_seg_size(fsl_edma->dma_dev.dev, 0x3fff);
586+
dma_set_max_seg_size(fsl_edma->dma_dev.dev,
587+
FIELD_GET(EDMA_TCD_ITER_MASK, EDMA_TCD_ITER_MASK));
586588

587589
fsl_edma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
588590

drivers/dma/fsl-qdma.c

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
#define FSL_QDMA_CMD_WTHROTL_OFFSET 20
110110
#define FSL_QDMA_CMD_DSEN_OFFSET 19
111111
#define FSL_QDMA_CMD_LWC_OFFSET 16
112+
#define FSL_QDMA_CMD_PF BIT(17)
112113

113114
/* Field definition for Descriptor status */
114115
#define QDMA_CCDF_STATUS_RTE BIT(5)
@@ -160,6 +161,10 @@ struct fsl_qdma_format {
160161
u8 __reserved1[2];
161162
u8 cfg8b_w1;
162163
} __packed;
164+
struct {
165+
__le32 __reserved2;
166+
__le32 cmd;
167+
} __packed;
163168
__le64 data;
164169
};
165170
} __packed;
@@ -354,7 +359,6 @@ static void fsl_qdma_free_chan_resources(struct dma_chan *chan)
354359
static void fsl_qdma_comp_fill_memcpy(struct fsl_qdma_comp *fsl_comp,
355360
dma_addr_t dst, dma_addr_t src, u32 len)
356361
{
357-
u32 cmd;
358362
struct fsl_qdma_format *sdf, *ddf;
359363
struct fsl_qdma_format *ccdf, *csgf_desc, *csgf_src, *csgf_dest;
360364

@@ -383,14 +387,11 @@ static void fsl_qdma_comp_fill_memcpy(struct fsl_qdma_comp *fsl_comp,
383387
/* This entry is the last entry. */
384388
qdma_csgf_set_f(csgf_dest, len);
385389
/* Descriptor Buffer */
386-
cmd = cpu_to_le32(FSL_QDMA_CMD_RWTTYPE <<
387-
FSL_QDMA_CMD_RWTTYPE_OFFSET);
388-
sdf->data = QDMA_SDDF_CMD(cmd);
389-
390-
cmd = cpu_to_le32(FSL_QDMA_CMD_RWTTYPE <<
391-
FSL_QDMA_CMD_RWTTYPE_OFFSET);
392-
cmd |= cpu_to_le32(FSL_QDMA_CMD_LWC << FSL_QDMA_CMD_LWC_OFFSET);
393-
ddf->data = QDMA_SDDF_CMD(cmd);
390+
sdf->cmd = cpu_to_le32((FSL_QDMA_CMD_RWTTYPE << FSL_QDMA_CMD_RWTTYPE_OFFSET) |
391+
FSL_QDMA_CMD_PF);
392+
393+
ddf->cmd = cpu_to_le32((FSL_QDMA_CMD_RWTTYPE << FSL_QDMA_CMD_RWTTYPE_OFFSET) |
394+
(FSL_QDMA_CMD_LWC << FSL_QDMA_CMD_LWC_OFFSET));
394395
}
395396

396397
/*
@@ -624,7 +625,7 @@ static int fsl_qdma_halt(struct fsl_qdma_engine *fsl_qdma)
624625

625626
static int
626627
fsl_qdma_queue_transfer_complete(struct fsl_qdma_engine *fsl_qdma,
627-
void *block,
628+
__iomem void *block,
628629
int id)
629630
{
630631
bool duplicate;
@@ -1196,10 +1197,6 @@ static int fsl_qdma_probe(struct platform_device *pdev)
11961197
if (!fsl_qdma->queue)
11971198
return -ENOMEM;
11981199

1199-
ret = fsl_qdma_irq_init(pdev, fsl_qdma);
1200-
if (ret)
1201-
return ret;
1202-
12031200
fsl_qdma->irq_base = platform_get_irq_byname(pdev, "qdma-queue0");
12041201
if (fsl_qdma->irq_base < 0)
12051202
return fsl_qdma->irq_base;
@@ -1238,16 +1235,19 @@ static int fsl_qdma_probe(struct platform_device *pdev)
12381235

12391236
platform_set_drvdata(pdev, fsl_qdma);
12401237

1241-
ret = dma_async_device_register(&fsl_qdma->dma_dev);
1238+
ret = fsl_qdma_reg_init(fsl_qdma);
12421239
if (ret) {
1243-
dev_err(&pdev->dev,
1244-
"Can't register NXP Layerscape qDMA engine.\n");
1240+
dev_err(&pdev->dev, "Can't Initialize the qDMA engine.\n");
12451241
return ret;
12461242
}
12471243

1248-
ret = fsl_qdma_reg_init(fsl_qdma);
1244+
ret = fsl_qdma_irq_init(pdev, fsl_qdma);
1245+
if (ret)
1246+
return ret;
1247+
1248+
ret = dma_async_device_register(&fsl_qdma->dma_dev);
12491249
if (ret) {
1250-
dev_err(&pdev->dev, "Can't Initialize the qDMA engine.\n");
1250+
dev_err(&pdev->dev, "Can't register NXP Layerscape qDMA engine.\n");
12511251
return ret;
12521252
}
12531253

drivers/dma/idxd/cdev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ static void idxd_cdev_evl_drain_pasid(struct idxd_wq *wq, u32 pasid)
345345
spin_lock(&evl->lock);
346346
status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
347347
t = status.tail;
348-
h = evl->head;
348+
h = status.head;
349349
size = evl->size;
350350

351351
while (h != t) {

drivers/dma/idxd/debugfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ static int debugfs_evl_show(struct seq_file *s, void *d)
6868

6969
spin_lock(&evl->lock);
7070

71-
h = evl->head;
7271
evl_status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
7372
t = evl_status.tail;
73+
h = evl_status.head;
7474
evl_size = evl->size;
7575

7676
seq_printf(s, "Event Log head %u tail %u interrupt pending %u\n\n",

drivers/dma/idxd/idxd.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,6 @@ struct idxd_evl {
300300
unsigned int log_size;
301301
/* The number of entries in the event log. */
302302
u16 size;
303-
u16 head;
304303
unsigned long *bmap;
305304
bool batch_fail[IDXD_MAX_BATCH_IDENT];
306305
};

drivers/dma/idxd/init.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,9 @@ static void idxd_cleanup_internals(struct idxd_device *idxd)
343343
static int idxd_init_evl(struct idxd_device *idxd)
344344
{
345345
struct device *dev = &idxd->pdev->dev;
346+
unsigned int evl_cache_size;
346347
struct idxd_evl *evl;
348+
const char *idxd_name;
347349

348350
if (idxd->hw.gen_cap.evl_support == 0)
349351
return 0;
@@ -355,9 +357,16 @@ static int idxd_init_evl(struct idxd_device *idxd)
355357
spin_lock_init(&evl->lock);
356358
evl->size = IDXD_EVL_SIZE_MIN;
357359

358-
idxd->evl_cache = kmem_cache_create(dev_name(idxd_confdev(idxd)),
359-
sizeof(struct idxd_evl_fault) + evl_ent_size(idxd),
360-
0, 0, NULL);
360+
idxd_name = dev_name(idxd_confdev(idxd));
361+
evl_cache_size = sizeof(struct idxd_evl_fault) + evl_ent_size(idxd);
362+
/*
363+
* Since completion record in evl_cache will be copied to user
364+
* when handling completion record page fault, need to create
365+
* the cache suitable for user copy.
366+
*/
367+
idxd->evl_cache = kmem_cache_create_usercopy(idxd_name, evl_cache_size,
368+
0, 0, 0, evl_cache_size,
369+
NULL);
361370
if (!idxd->evl_cache) {
362371
kfree(evl);
363372
return -ENOMEM;

drivers/dma/idxd/irq.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,9 @@ static void process_evl_entries(struct idxd_device *idxd)
367367
/* Clear interrupt pending bit */
368368
iowrite32(evl_status.bits_upper32,
369369
idxd->reg_base + IDXD_EVLSTATUS_OFFSET + sizeof(u32));
370-
h = evl->head;
371370
evl_status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
372371
t = evl_status.tail;
372+
h = evl_status.head;
373373
size = idxd->evl->size;
374374

375375
while (h != t) {
@@ -378,7 +378,6 @@ static void process_evl_entries(struct idxd_device *idxd)
378378
h = (h + 1) % size;
379379
}
380380

381-
evl->head = h;
382381
evl_status.head = h;
383382
iowrite32(evl_status.bits_lower32, idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
384383
spin_unlock(&evl->lock);

drivers/dma/ptdma/ptdma-dmaengine.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,6 @@ int pt_dmaengine_register(struct pt_device *pt)
385385
chan->vc.desc_free = pt_do_cleanup;
386386
vchan_init(&chan->vc, dma_dev);
387387

388-
dma_set_mask_and_coherent(pt->dev, DMA_BIT_MASK(64));
389-
390388
ret = dma_async_device_register(dma_dev);
391389
if (ret)
392390
goto err_reg;

0 commit comments

Comments
 (0)