Skip to content

Commit a195c7c

Browse files
Jason-JH LinJassi Brar
authored andcommitted
mailbox: mtk-cmdq: Refine DMA address handling for the command buffer
GCE can only fetch the command buffer address from a 32-bit register. Some SoCs support a 35-bit command buffer address for GCE, which requires a right shift of 3 bits before setting the address into the 32-bit register. A comment has been added to the header of cmdq_get_shift_pa() to explain this requirement. To prevent the GCE command buffer address from being DMA mapped beyond its supported bit range, the DMA bit mask for the device is set during initialization. Additionally, to ensure the correct shift is applied when setting or reading the register that stores the GCE command buffer address, new APIs, cmdq_convert_gce_addr() and cmdq_revert_gce_addr(), have been introduced for consistent operations on this register. The variable type for the command buffer address has been standardized to dma_addr_t to prevent handling issues caused by type mismatches. Fixes: 0858fde ("mailbox: cmdq: variablize address shift in platform") Signed-off-by: Jason-JH Lin <jason-jh.lin@mediatek.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
1 parent 3acf102 commit a195c7c

2 files changed

Lines changed: 41 additions & 14 deletions

File tree

drivers/mailbox/mtk-cmdq-mailbox.c

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ struct gce_plat {
9292
u32 gce_num;
9393
};
9494

95+
static inline u32 cmdq_convert_gce_addr(dma_addr_t addr, const struct gce_plat *pdata)
96+
{
97+
/* Convert DMA addr (PA or IOVA) to GCE readable addr */
98+
return addr >> pdata->shift;
99+
}
100+
101+
static inline dma_addr_t cmdq_revert_gce_addr(u32 addr, const struct gce_plat *pdata)
102+
{
103+
/* Revert GCE readable addr to DMA addr (PA or IOVA) */
104+
return (dma_addr_t)addr << pdata->shift;
105+
}
106+
95107
u8 cmdq_get_shift_pa(struct mbox_chan *chan)
96108
{
97109
struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox);
@@ -188,13 +200,12 @@ static void cmdq_task_insert_into_thread(struct cmdq_task *task)
188200
struct cmdq_task *prev_task = list_last_entry(
189201
&thread->task_busy_list, typeof(*task), list_entry);
190202
u64 *prev_task_base = prev_task->pkt->va_base;
203+
u32 gce_addr = cmdq_convert_gce_addr(task->pa_base, task->cmdq->pdata);
191204

192205
/* let previous task jump to this task */
193206
dma_sync_single_for_cpu(dev, prev_task->pa_base,
194207
prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE);
195-
prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] =
196-
(u64)CMDQ_JUMP_BY_PA << 32 |
197-
(task->pa_base >> task->cmdq->pdata->shift);
208+
prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] = (u64)CMDQ_JUMP_BY_PA << 32 | gce_addr;
198209
dma_sync_single_for_device(dev, prev_task->pa_base,
199210
prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE);
200211

@@ -237,7 +248,8 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq,
237248
struct cmdq_thread *thread)
238249
{
239250
struct cmdq_task *task, *tmp, *curr_task = NULL;
240-
u32 curr_pa, irq_flag, task_end_pa;
251+
u32 irq_flag, gce_addr;
252+
dma_addr_t curr_pa, task_end_pa;
241253
bool err;
242254

243255
irq_flag = readl(thread->base + CMDQ_THR_IRQ_STATUS);
@@ -259,7 +271,8 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq,
259271
else
260272
return;
261273

262-
curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << cmdq->pdata->shift;
274+
gce_addr = readl(thread->base + CMDQ_THR_CURR_ADDR);
275+
curr_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata);
263276

264277
list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
265278
list_entry) {
@@ -378,7 +391,8 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
378391
struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv;
379392
struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev);
380393
struct cmdq_task *task;
381-
unsigned long curr_pa, end_pa;
394+
u32 gce_addr;
395+
dma_addr_t curr_pa, end_pa;
382396

383397
/* Client should not flush new tasks if suspended. */
384398
WARN_ON(cmdq->suspended);
@@ -402,20 +416,20 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
402416
*/
403417
WARN_ON(cmdq_thread_reset(cmdq, thread) < 0);
404418

405-
writel(task->pa_base >> cmdq->pdata->shift,
406-
thread->base + CMDQ_THR_CURR_ADDR);
407-
writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->pdata->shift,
408-
thread->base + CMDQ_THR_END_ADDR);
419+
gce_addr = cmdq_convert_gce_addr(task->pa_base, cmdq->pdata);
420+
writel(gce_addr, thread->base + CMDQ_THR_CURR_ADDR);
421+
gce_addr = cmdq_convert_gce_addr(task->pa_base + pkt->cmd_buf_size, cmdq->pdata);
422+
writel(gce_addr, thread->base + CMDQ_THR_END_ADDR);
409423

410424
writel(thread->priority, thread->base + CMDQ_THR_PRIORITY);
411425
writel(CMDQ_THR_IRQ_EN, thread->base + CMDQ_THR_IRQ_ENABLE);
412426
writel(CMDQ_THR_ENABLED, thread->base + CMDQ_THR_ENABLE_TASK);
413427
} else {
414428
WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
415-
curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) <<
416-
cmdq->pdata->shift;
417-
end_pa = readl(thread->base + CMDQ_THR_END_ADDR) <<
418-
cmdq->pdata->shift;
429+
gce_addr = readl(thread->base + CMDQ_THR_CURR_ADDR);
430+
curr_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata);
431+
gce_addr = readl(thread->base + CMDQ_THR_END_ADDR);
432+
end_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata);
419433
/* check boundary */
420434
if (curr_pa == end_pa - CMDQ_INST_SIZE ||
421435
curr_pa == end_pa) {
@@ -646,6 +660,9 @@ static int cmdq_probe(struct platform_device *pdev)
646660
if (err)
647661
return err;
648662

663+
dma_set_coherent_mask(dev,
664+
DMA_BIT_MASK(sizeof(u32) * BITS_PER_BYTE + cmdq->pdata->shift));
665+
649666
cmdq->mbox.dev = dev;
650667
cmdq->mbox.chans = devm_kcalloc(dev, cmdq->pdata->thread_nr,
651668
sizeof(*cmdq->mbox.chans), GFP_KERNEL);

include/linux/mailbox/mtk-cmdq-mailbox.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ struct cmdq_pkt {
7777
size_t buf_size; /* real buffer size */
7878
};
7979

80+
/**
81+
* cmdq_get_shift_pa() - get the shift bits of physical address
82+
* @chan: mailbox channel
83+
*
84+
* GCE can only fetch the command buffer address from a 32-bit register.
85+
* Some SOCs support more than 32-bit command buffer address for GCE, which
86+
* requires some shift bits to make the address fit into the 32-bit register.
87+
*
88+
* Return: the shift bits of physical address
89+
*/
8090
u8 cmdq_get_shift_pa(struct mbox_chan *chan);
8191

8292
#endif /* __MTK_CMDQ_MAILBOX_H__ */

0 commit comments

Comments
 (0)