Pull mailbox fixes from Jassi Brar: - omap: check for pending msgs only when mbox is exclusive - mailbox-test: debugfs_create_dir error checking - mtk: - cmdq: fix DMA address handling - gpueb: Add missing 'static' to mailbox ops struct - pcc: don't zero error register - th1520: fix clock imbalance on probe failure * tag 'mailbox-fixes-v6.18-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox: mailbox: th1520: fix clock imbalance on probe failure mailbox: pcc: don't zero error register mailbox: mtk-gpueb: Add missing 'static' to mailbox ops struct mailbox: mtk-cmdq: Refine DMA address handling for the command buffer mailbox: mailbox-test: Fix debugfs_create_dir error checking mailbox: omap-mailbox: Check for pending msgs only when mbox is exclusive
Unified · Split
| @@ -268,7 +268,7 @@ static int mbox_test_add_debugfs(struct platform_device *pdev, · 267 unmodified lines | ||
| 268 | 268 | return 0; |
| 269 | 269 | |
| 270 | 270 | tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL); |
| 271 | − if (!tdev->root_debugfs_dir) { | |
| 271 | + if (IS_ERR(tdev->root_debugfs_dir)) { | |
| 272 | 272 | dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n"); |
| 273 | 273 | return -EINVAL; |
| 274 | 274 | } |
| @@ -435,10 +435,8 @@ static int th1520_mbox_probe(struct platform_device *pdev) · 434 unmodified lines | ||
| 435 | 435 | } |
| 436 | 436 | |
| 437 | 437 | ret = devm_add_action_or_reset(dev, th1520_disable_clk, priv); |
| 438 | − if (ret) { | |
| 439 | − clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks); | |
| 438 | + if (ret) | |
| 440 | 439 | return ret; |
| 441 | − } | |
| 442 | 440 | |
| 443 | 441 | /* |
| 444 | 442 | * The address mappings in the device tree align precisely with those |
| @@ -92,6 +92,18 @@ struct gce_plat { · 91 unmodified lines | ||
| 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); |
| @@ -188,13 +200,12 @@ static void cmdq_task_insert_into_thread(struct cmdq_task *task) · 90 unmodified lines | ||
| 188 | 200 | struct cmdq_task *prev_task = list_last_entry( |
| 189 | 201 | &thread->task_busy_list, typeof(*task), list_entry); |
| 190 | 202 | u64 *prev_task_base = prev_task->pkt->va_base; |
| 203 | + u32 gce_addr = cmdq_convert_gce_addr(task->pa_base, task->cmdq->pdata); | |
| 191 | 204 | |
| 192 | 205 | /* let previous task jump to this task */ |
| 193 | 206 | dma_sync_single_for_cpu(dev, prev_task->pa_base, |
| 194 | 207 | 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; | |
| 198 | 209 | dma_sync_single_for_device(dev, prev_task->pa_base, |
| 199 | 210 | prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE); |
| 200 | 211 | |
| @@ -237,7 +248,8 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq, · 36 unmodified lines | ||
| 237 | 248 | struct cmdq_thread *thread) |
| 238 | 249 | { |
| 239 | 250 | 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; | |
| 241 | 253 | bool err; |
| 242 | 254 | |
| 243 | 255 | irq_flag = readl(thread->base + CMDQ_THR_IRQ_STATUS); |
| @@ -259,7 +271,8 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq, · 15 unmodified lines | ||
| 259 | 271 | else |
| 260 | 272 | return; |
| 261 | 273 | |
| 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); | |
| 263 | 276 | |
| 264 | 277 | list_for_each_entry_safe(task, tmp, &thread->task_busy_list, |
| 265 | 278 | list_entry) { |
| @@ -378,7 +391,8 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) · 112 unmodified lines | ||
| 378 | 391 | struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv; |
| 379 | 392 | struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); |
| 380 | 393 | struct cmdq_task *task; |
| 381 | − unsigned long curr_pa, end_pa; | |
| 394 | + u32 gce_addr; | |
| 395 | + dma_addr_t curr_pa, end_pa; | |
| 382 | 396 | |
| 383 | 397 | /* Client should not flush new tasks if suspended. */ |
| 384 | 398 | WARN_ON(cmdq->suspended); |
| @@ -402,20 +416,20 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) · 17 unmodified lines | ||
| 402 | 416 | */ |
| 403 | 417 | WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); |
| 404 | 418 | |
| 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); | |
| 409 | 423 | |
| 410 | 424 | writel(thread->priority, thread->base + CMDQ_THR_PRIORITY); |
| 411 | 425 | writel(CMDQ_THR_IRQ_EN, thread->base + CMDQ_THR_IRQ_ENABLE); |
| 412 | 426 | writel(CMDQ_THR_ENABLED, thread->base + CMDQ_THR_ENABLE_TASK); |
| 413 | 427 | } else { |
| 414 | 428 | 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); | |
| 419 | 433 | /* check boundary */ |
| 420 | 434 | if (curr_pa == end_pa - CMDQ_INST_SIZE || |
| 421 | 435 | curr_pa == end_pa) { |
| @@ -646,6 +660,9 @@ static int cmdq_probe(struct platform_device *pdev) · 224 unmodified lines | ||
| 646 | 660 | if (err) |
| 647 | 661 | return err; |
| 648 | 662 | |
| 663 | + dma_set_coherent_mask(dev, | |
| 664 | + DMA_BIT_MASK(sizeof(u32) * BITS_PER_BYTE + cmdq->pdata->shift)); | |
| 665 | + | |
| 649 | 666 | cmdq->mbox.dev = dev; |
| 650 | 667 | cmdq->mbox.chans = devm_kcalloc(dev, cmdq->pdata->thread_nr, |
| 651 | 668 | sizeof(*cmdq->mbox.chans), GFP_KERNEL); |
| @@ -200,7 +200,7 @@ static bool mtk_gpueb_mbox_last_tx_done(struct mbox_chan *chan) · 199 unmodified lines | ||
| 200 | 200 | return !(readl(ch->ebm->mbox_ctl + GPUEB_MBOX_CTL_TX_STS) & BIT(ch->num)); |
| 201 | 201 | } |
| 202 | 202 | |
| 203 | −const struct mbox_chan_ops mtk_gpueb_mbox_ops = { | |
| 203 | +static const struct mbox_chan_ops mtk_gpueb_mbox_ops = { | |
| 204 | 204 | .send_data = mtk_gpueb_mbox_send_data, |
| 205 | 205 | .startup = mtk_gpueb_mbox_startup, |
| 206 | 206 | .shutdown = mtk_gpueb_mbox_shutdown, |
| @@ -68,6 +68,7 @@ struct omap_mbox_fifo { · 67 unmodified lines | ||
| 68 | 68 | |
| 69 | 69 | struct omap_mbox_match_data { |
| 70 | 70 | u32 intr_type; |
| 71 | + bool is_exclusive; | |
| 71 | 72 | }; |
| 72 | 73 | |
| 73 | 74 | struct omap_mbox_device { |
| @@ -78,6 +79,7 @@ struct omap_mbox_device { · 4 unmodified lines | ||
| 78 | 79 | u32 num_users; |
| 79 | 80 | u32 num_fifos; |
| 80 | 81 | u32 intr_type; |
| 82 | + const struct omap_mbox_match_data *mbox_data; | |
| 81 | 83 | }; |
| 82 | 84 | |
| 83 | 85 | struct omap_mbox { |
| @@ -341,11 +343,13 @@ static int omap_mbox_suspend(struct device *dev) · 257 unmodified lines | ||
| 341 | 343 | if (pm_runtime_status_suspended(dev)) |
| 342 | 344 | return 0; |
| 343 | 345 | |
| 344 | − for (fifo = 0; fifo < mdev->num_fifos; fifo++) { | |
| 345 | − if (mbox_read_reg(mdev, MAILBOX_MSGSTATUS(fifo))) { | |
| 346 | − dev_err(mdev->dev, "fifo %d has unexpected unread messages\n", | |
| 347 | − fifo); | |
| 348 | − return -EBUSY; | |
| 346 | + if (mdev->mbox_data->is_exclusive) { | |
| 347 | + for (fifo = 0; fifo < mdev->num_fifos; fifo++) { | |
| 348 | + if (mbox_read_reg(mdev, MAILBOX_MSGSTATUS(fifo))) { | |
| 349 | + dev_err(mdev->dev, "fifo %d has unexpected unread messages\n", | |
| 350 | + fifo); | |
| 351 | + return -EBUSY; | |
| 352 | + } | |
| 349 | 353 | } |
| 350 | 354 | } |
| 351 | 355 | |
| @@ -378,8 +382,9 @@ static const struct dev_pm_ops omap_mbox_pm_ops = { · 26 unmodified lines | ||
| 378 | 382 | SET_SYSTEM_SLEEP_PM_OPS(omap_mbox_suspend, omap_mbox_resume) |
| 379 | 383 | }; |
| 380 | 384 | |
| 381 | −static const struct omap_mbox_match_data omap2_data = { MBOX_INTR_CFG_TYPE1 }; | |
| 382 | −static const struct omap_mbox_match_data omap4_data = { MBOX_INTR_CFG_TYPE2 }; | |
| 385 | +static const struct omap_mbox_match_data omap2_data = { MBOX_INTR_CFG_TYPE1, true }; | |
| 386 | +static const struct omap_mbox_match_data omap4_data = { MBOX_INTR_CFG_TYPE2, true }; | |
| 387 | +static const struct omap_mbox_match_data am654_data = { MBOX_INTR_CFG_TYPE2, false }; | |
| 383 | 388 | |
| 384 | 389 | static const struct of_device_id omap_mailbox_of_match[] = { |
| 385 | 390 | { |
| @@ -396,11 +401,11 @@ static const struct of_device_id omap_mailbox_of_match[] = { · 10 unmodified lines | ||
| 396 | 401 | }, |
| 397 | 402 | { |
| 398 | 403 | .compatible = "ti,am654-mailbox", |
| 399 | − .data = &omap4_data, | |
| 404 | + .data = &am654_data, | |
| 400 | 405 | }, |
| 401 | 406 | { |
| 402 | 407 | .compatible = "ti,am64-mailbox", |
| 403 | − .data = &omap4_data, | |
| 408 | + .data = &am654_data, | |
| 404 | 409 | }, |
| 405 | 410 | { |
| 406 | 411 | /* end */ |
| @@ -449,7 +454,6 @@ static int omap_mbox_probe(struct platform_device *pdev) · 42 unmodified lines | ||
| 449 | 454 | struct omap_mbox_fifo *fifo; |
| 450 | 455 | struct device_node *node = pdev->dev.of_node; |
| 451 | 456 | struct device_node *child; |
| 452 | − const struct omap_mbox_match_data *match_data; | |
| 453 | 457 | struct mbox_controller *controller; |
| 454 | 458 | u32 intr_type, info_count; |
| 455 | 459 | u32 num_users, num_fifos; |
| @@ -462,11 +466,6 @@ static int omap_mbox_probe(struct platform_device *pdev) · 6 unmodified lines | ||
| 462 | 466 | return -ENODEV; |
| 463 | 467 | } |
| 464 | 468 | |
| 465 | − match_data = of_device_get_match_data(&pdev->dev); | |
| 466 | − if (!match_data) | |
| 467 | − return -ENODEV; | |
| 468 | − intr_type = match_data->intr_type; | |
| 469 | − | |
| 470 | 469 | if (of_property_read_u32(node, "ti,mbox-num-users", &num_users)) |
| 471 | 470 | return -ENODEV; |
| 472 | 471 | |
| @@ -483,6 +482,12 @@ static int omap_mbox_probe(struct platform_device *pdev) · 10 unmodified lines | ||
| 483 | 482 | if (!mdev) |
| 484 | 483 | return -ENOMEM; |
| 485 | 484 | |
| 485 | + mdev->mbox_data = device_get_match_data(&pdev->dev); | |
| 486 | + if (!mdev->mbox_data) | |
| 487 | + return -ENODEV; | |
| 488 | + | |
| 489 | + intr_type = mdev->mbox_data->intr_type; | |
| 490 | + | |
| 486 | 491 | mdev->mbox_base = devm_platform_ioremap_resource(pdev, 0); |
| 487 | 492 | if (IS_ERR(mdev->mbox_base)) |
| 488 | 493 | return PTR_ERR(mdev->mbox_base); |
| @@ -276,9 +276,8 @@ static int pcc_mbox_error_check_and_clear(struct pcc_chan_info *pchan) · 275 unmodified lines | ||
| 276 | 276 | if (ret) |
| 277 | 277 | return ret; |
| 278 | 278 | |
| 279 | − val &= pchan->error.status_mask; | |
| 280 | − if (val) { | |
| 281 | − val &= ~pchan->error.status_mask; | |
| 279 | + if (val & pchan->error.status_mask) { | |
| 280 | + val &= pchan->error.preserve_mask; | |
| 282 | 281 | pcc_chan_reg_write(&pchan->error, val); |
| 283 | 282 | return -EIO; |
| 284 | 283 | } |
| @@ -745,7 +744,8 @@ static int pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan, · 460 unmodified lines | ||
| 745 | 744 | |
| 746 | 745 | ret = pcc_chan_reg_init(&pchan->error, |
| 747 | 746 | &pcct_ext->error_status_register, |
| 748 | − 0, 0, pcct_ext->error_status_mask, | |
| 747 | + ~pcct_ext->error_status_mask, 0, | |
| 748 | + pcct_ext->error_status_mask, | |
| 749 | 749 | "Error Status"); |
| 750 | 750 | } |
| 751 | 751 | return ret; |
| @@ -77,6 +77,16 @@ struct cmdq_pkt { · 76 unmodified lines | ||
| 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__ */ |