Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 0858fde496f8 ("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>

authored by

Jason-JH Lin and committed by
Jassi Brar
a195c7cc 3acf1028

+41 -14
+31 -14
drivers/mailbox/mtk-cmdq-mailbox.c
··· 92 92 u32 gce_num; 93 93 }; 94 94 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 + 95 107 u8 cmdq_get_shift_pa(struct mbox_chan *chan) 96 108 { 97 109 struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox); ··· 200 188 struct cmdq_task *prev_task = list_last_entry( 201 189 &thread->task_busy_list, typeof(*task), list_entry); 202 190 u64 *prev_task_base = prev_task->pkt->va_base; 191 + u32 gce_addr = cmdq_convert_gce_addr(task->pa_base, task->cmdq->pdata); 203 192 204 193 /* let previous task jump to this task */ 205 194 dma_sync_single_for_cpu(dev, prev_task->pa_base, 206 195 prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE); 207 - prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] = 208 - (u64)CMDQ_JUMP_BY_PA << 32 | 209 - (task->pa_base >> task->cmdq->pdata->shift); 196 + prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] = (u64)CMDQ_JUMP_BY_PA << 32 | gce_addr; 210 197 dma_sync_single_for_device(dev, prev_task->pa_base, 211 198 prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE); 212 199 ··· 248 237 struct cmdq_thread *thread) 249 238 { 250 239 struct cmdq_task *task, *tmp, *curr_task = NULL; 251 - u32 curr_pa, irq_flag, task_end_pa; 240 + u32 irq_flag, gce_addr; 241 + dma_addr_t curr_pa, task_end_pa; 252 242 bool err; 253 243 254 244 irq_flag = readl(thread->base + CMDQ_THR_IRQ_STATUS); ··· 271 259 else 272 260 return; 273 261 274 - curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << cmdq->pdata->shift; 262 + gce_addr = readl(thread->base + CMDQ_THR_CURR_ADDR); 263 + curr_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata); 275 264 276 265 list_for_each_entry_safe(task, tmp, &thread->task_busy_list, 277 266 list_entry) { ··· 391 378 struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv; 392 379 struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); 393 380 struct cmdq_task *task; 394 - unsigned long curr_pa, end_pa; 381 + u32 gce_addr; 382 + dma_addr_t curr_pa, end_pa; 395 383 396 384 /* Client should not flush new tasks if suspended. */ 397 385 WARN_ON(cmdq->suspended); ··· 416 402 */ 417 403 WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); 418 404 419 - writel(task->pa_base >> cmdq->pdata->shift, 420 - thread->base + CMDQ_THR_CURR_ADDR); 421 - writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->pdata->shift, 422 - thread->base + CMDQ_THR_END_ADDR); 405 + gce_addr = cmdq_convert_gce_addr(task->pa_base, cmdq->pdata); 406 + writel(gce_addr, thread->base + CMDQ_THR_CURR_ADDR); 407 + gce_addr = cmdq_convert_gce_addr(task->pa_base + pkt->cmd_buf_size, cmdq->pdata); 408 + writel(gce_addr, thread->base + CMDQ_THR_END_ADDR); 423 409 424 410 writel(thread->priority, thread->base + CMDQ_THR_PRIORITY); 425 411 writel(CMDQ_THR_IRQ_EN, thread->base + CMDQ_THR_IRQ_ENABLE); 426 412 writel(CMDQ_THR_ENABLED, thread->base + CMDQ_THR_ENABLE_TASK); 427 413 } else { 428 414 WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); 429 - curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << 430 - cmdq->pdata->shift; 431 - end_pa = readl(thread->base + CMDQ_THR_END_ADDR) << 432 - cmdq->pdata->shift; 415 + gce_addr = readl(thread->base + CMDQ_THR_CURR_ADDR); 416 + curr_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata); 417 + gce_addr = readl(thread->base + CMDQ_THR_END_ADDR); 418 + end_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata); 433 419 /* check boundary */ 434 420 if (curr_pa == end_pa - CMDQ_INST_SIZE || 435 421 curr_pa == end_pa) { ··· 659 645 err = cmdq_get_clocks(dev, cmdq); 660 646 if (err) 661 647 return err; 648 + 649 + dma_set_coherent_mask(dev, 650 + DMA_BIT_MASK(sizeof(u32) * BITS_PER_BYTE + cmdq->pdata->shift)); 662 651 663 652 cmdq->mbox.dev = dev; 664 653 cmdq->mbox.chans = devm_kcalloc(dev, cmdq->pdata->thread_nr,
+10
include/linux/mailbox/mtk-cmdq-mailbox.h
··· 77 77 size_t buf_size; /* real buffer size */ 78 78 }; 79 79 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 + */ 80 90 u8 cmdq_get_shift_pa(struct mbox_chan *chan); 81 91 82 92 #endif /* __MTK_CMDQ_MAILBOX_H__ */