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 | return 0; | 268 | return 0; |
| 269 | 269 | ||
| 270 | tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL); | 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 | dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n"); | 272 | dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n"); |
| 273 | return -EINVAL; | 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 | ret = devm_add_action_or_reset(dev, th1520_disable_clk, priv); | 437 | ret = devm_add_action_or_reset(dev, th1520_disable_clk, priv); |
| 438 | if (ret) { | 438 | if (ret) |
| 439 | clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks); | ||
| 440 | return ret; | 439 | return ret; |
| 441 | } | ||
| 442 | 440 | ||
| 443 | /* | 441 | /* |
| 444 | * The address mappings in the device tree align precisely with those | 442 | * The address mappings in the device tree align precisely with those |
| @@ -92,6 +92,18 @@ struct gce_plat { · 91 unmodified lines | |||
| 92 | u32 gce_num; | 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 | u8 cmdq_get_shift_pa(struct mbox_chan *chan) | 107 | u8 cmdq_get_shift_pa(struct mbox_chan *chan) |
| 96 | { | 108 | { |
| 97 | struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox); | 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 | struct cmdq_task *prev_task = list_last_entry( | 200 | struct cmdq_task *prev_task = list_last_entry( |
| 189 | &thread->task_busy_list, typeof(*task), list_entry); | 201 | &thread->task_busy_list, typeof(*task), list_entry); |
| 190 | u64 *prev_task_base = prev_task->pkt->va_base; | 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 | /* let previous task jump to this task */ | 205 | /* let previous task jump to this task */ |
| 193 | dma_sync_single_for_cpu(dev, prev_task->pa_base, | 206 | dma_sync_single_for_cpu(dev, prev_task->pa_base, |
| 194 | prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE); | 207 | prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE); |
| 195 | prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] = | 208 | prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] = (u64)CMDQ_JUMP_BY_PA << 32 | gce_addr; |
| 196 | (u64)CMDQ_JUMP_BY_PA << 32 | | ||
| 197 | (task->pa_base >> task->cmdq->pdata->shift); | ||
| 198 | dma_sync_single_for_device(dev, prev_task->pa_base, | 209 | dma_sync_single_for_device(dev, prev_task->pa_base, |
| 199 | prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE); | 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 | struct cmdq_thread *thread) | 248 | struct cmdq_thread *thread) |
| 238 | { | 249 | { |
| 239 | struct cmdq_task *task, *tmp, *curr_task = NULL; | 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 | bool err; | 253 | bool err; |
| 242 | 254 | ||
| 243 | irq_flag = readl(thread->base + CMDQ_THR_IRQ_STATUS); | 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 | else | 271 | else |
| 260 | return; | 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 | list_for_each_entry_safe(task, tmp, &thread->task_busy_list, | 277 | list_for_each_entry_safe(task, tmp, &thread->task_busy_list, |
| 265 | list_entry) { | 278 | list_entry) { |
| @@ -378,7 +391,8 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) · 112 unmodified lines | |||
| 378 | struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv; | 391 | struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv; |
| 379 | struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); | 392 | struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); |
| 380 | struct cmdq_task *task; | 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 | /* Client should not flush new tasks if suspended. */ | 397 | /* Client should not flush new tasks if suspended. */ |
| 384 | WARN_ON(cmdq->suspended); | 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 | WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); | 417 | WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); |
| 404 | 418 | ||
| 405 | writel(task->pa_base >> cmdq->pdata->shift, | 419 | gce_addr = cmdq_convert_gce_addr(task->pa_base, cmdq->pdata); |
| 406 | thread->base + CMDQ_THR_CURR_ADDR); | 420 | writel(gce_addr, thread->base + CMDQ_THR_CURR_ADDR); |
| 407 | writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->pdata->shift, | 421 | gce_addr = cmdq_convert_gce_addr(task->pa_base + pkt->cmd_buf_size, cmdq->pdata); |
| 408 | thread->base + CMDQ_THR_END_ADDR); | 422 | writel(gce_addr, thread->base + CMDQ_THR_END_ADDR); |
| 409 | 423 | ||
| 410 | writel(thread->priority, thread->base + CMDQ_THR_PRIORITY); | 424 | writel(thread->priority, thread->base + CMDQ_THR_PRIORITY); |
| 411 | writel(CMDQ_THR_IRQ_EN, thread->base + CMDQ_THR_IRQ_ENABLE); | 425 | writel(CMDQ_THR_IRQ_EN, thread->base + CMDQ_THR_IRQ_ENABLE); |
| 412 | writel(CMDQ_THR_ENABLED, thread->base + CMDQ_THR_ENABLE_TASK); | 426 | writel(CMDQ_THR_ENABLED, thread->base + CMDQ_THR_ENABLE_TASK); |
| 413 | } else { | 427 | } else { |
| 414 | WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); | 428 | WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); |
| 415 | curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << | 429 | gce_addr = readl(thread->base + CMDQ_THR_CURR_ADDR); |
| 416 | cmdq->pdata->shift; | 430 | curr_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata); |
| 417 | end_pa = readl(thread->base + CMDQ_THR_END_ADDR) << | 431 | gce_addr = readl(thread->base + CMDQ_THR_END_ADDR); |
| 418 | cmdq->pdata->shift; | 432 | end_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata); |
| 419 | /* check boundary */ | 433 | /* check boundary */ |
| 420 | if (curr_pa == end_pa - CMDQ_INST_SIZE || | 434 | if (curr_pa == end_pa - CMDQ_INST_SIZE || |
| 421 | curr_pa == end_pa) { | 435 | curr_pa == end_pa) { |
| @@ -646,6 +660,9 @@ static int cmdq_probe(struct platform_device *pdev) · 224 unmodified lines | |||
| 646 | if (err) | 660 | if (err) |
| 647 | return err; | 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 | cmdq->mbox.dev = dev; | 666 | cmdq->mbox.dev = dev; |
| 650 | cmdq->mbox.chans = devm_kcalloc(dev, cmdq->pdata->thread_nr, | 667 | cmdq->mbox.chans = devm_kcalloc(dev, cmdq->pdata->thread_nr, |
| 651 | sizeof(*cmdq->mbox.chans), GFP_KERNEL); | 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 | return !(readl(ch->ebm->mbox_ctl + GPUEB_MBOX_CTL_TX_STS) & BIT(ch->num)); | 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 | .send_data = mtk_gpueb_mbox_send_data, | 204 | .send_data = mtk_gpueb_mbox_send_data, |
| 205 | .startup = mtk_gpueb_mbox_startup, | 205 | .startup = mtk_gpueb_mbox_startup, |
| 206 | .shutdown = mtk_gpueb_mbox_shutdown, | 206 | .shutdown = mtk_gpueb_mbox_shutdown, |
| @@ -68,6 +68,7 @@ struct omap_mbox_fifo { · 67 unmodified lines | |||
| 68 | 68 | ||
| 69 | struct omap_mbox_match_data { | 69 | struct omap_mbox_match_data { |
| 70 | u32 intr_type; | 70 | u32 intr_type; |
| 71 | bool is_exclusive; | ||
| 71 | }; | 72 | }; |
| 72 | 73 | ||
| 73 | struct omap_mbox_device { | 74 | struct omap_mbox_device { |
| @@ -78,6 +79,7 @@ struct omap_mbox_device { · 4 unmodified lines | |||
| 78 | u32 num_users; | 79 | u32 num_users; |
| 79 | u32 num_fifos; | 80 | u32 num_fifos; |
| 80 | u32 intr_type; | 81 | u32 intr_type; |
| 82 | const struct omap_mbox_match_data *mbox_data; | ||
| 81 | }; | 83 | }; |
| 82 | 84 | ||
| 83 | struct omap_mbox { | 85 | struct omap_mbox { |
| @@ -341,11 +343,13 @@ static int omap_mbox_suspend(struct device *dev) · 257 unmodified lines | |||
| 341 | if (pm_runtime_status_suspended(dev)) | 343 | if (pm_runtime_status_suspended(dev)) |
| 342 | return 0; | 344 | return 0; |
| 343 | 345 | ||
| 344 | for (fifo = 0; fifo < mdev->num_fifos; fifo++) { | 346 | if (mdev->mbox_data->is_exclusive) { |
| 345 | if (mbox_read_reg(mdev, MAILBOX_MSGSTATUS(fifo))) { | 347 | for (fifo = 0; fifo < mdev->num_fifos; fifo++) { |
| 346 | dev_err(mdev->dev, "fifo %d has unexpected unread messages\n", | 348 | if (mbox_read_reg(mdev, MAILBOX_MSGSTATUS(fifo))) { |
| 347 | fifo); | 349 | dev_err(mdev->dev, "fifo %d has unexpected unread messages\n", |
| 348 | return -EBUSY; | 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 | SET_SYSTEM_SLEEP_PM_OPS(omap_mbox_suspend, omap_mbox_resume) | 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 }; | 385 | static const struct omap_mbox_match_data omap2_data = { MBOX_INTR_CFG_TYPE1, true }; |
| 382 | static const struct omap_mbox_match_data omap4_data = { MBOX_INTR_CFG_TYPE2 }; | 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 | static const struct of_device_id omap_mailbox_of_match[] = { | 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 | .compatible = "ti,am654-mailbox", | 403 | .compatible = "ti,am654-mailbox", |
| 399 | .data = &omap4_data, | 404 | .data = &am654_data, |
| 400 | }, | 405 | }, |
| 401 | { | 406 | { |
| 402 | .compatible = "ti,am64-mailbox", | 407 | .compatible = "ti,am64-mailbox", |
| 403 | .data = &omap4_data, | 408 | .data = &am654_data, |
| 404 | }, | 409 | }, |
| 405 | { | 410 | { |
| 406 | /* end */ | 411 | /* end */ |
| @@ -449,7 +454,6 @@ static int omap_mbox_probe(struct platform_device *pdev) · 42 unmodified lines | |||
| 449 | struct omap_mbox_fifo *fifo; | 454 | struct omap_mbox_fifo *fifo; |
| 450 | struct device_node *node = pdev->dev.of_node; | 455 | struct device_node *node = pdev->dev.of_node; |
| 451 | struct device_node *child; | 456 | struct device_node *child; |
| 452 | const struct omap_mbox_match_data *match_data; | ||
| 453 | struct mbox_controller *controller; | 457 | struct mbox_controller *controller; |
| 454 | u32 intr_type, info_count; | 458 | u32 intr_type, info_count; |
| 455 | u32 num_users, num_fifos; | 459 | u32 num_users, num_fifos; |
| @@ -462,11 +466,6 @@ static int omap_mbox_probe(struct platform_device *pdev) · 6 unmodified lines | |||
| 462 | return -ENODEV; | 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 | if (of_property_read_u32(node, "ti,mbox-num-users", &num_users)) | 469 | if (of_property_read_u32(node, "ti,mbox-num-users", &num_users)) |
| 471 | return -ENODEV; | 470 | return -ENODEV; |
| 472 | 471 | ||
| @@ -483,6 +482,12 @@ static int omap_mbox_probe(struct platform_device *pdev) · 10 unmodified lines | |||
| 483 | if (!mdev) | 482 | if (!mdev) |
| 484 | return -ENOMEM; | 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 | mdev->mbox_base = devm_platform_ioremap_resource(pdev, 0); | 491 | mdev->mbox_base = devm_platform_ioremap_resource(pdev, 0); |
| 487 | if (IS_ERR(mdev->mbox_base)) | 492 | if (IS_ERR(mdev->mbox_base)) |
| 488 | return PTR_ERR(mdev->mbox_base); | 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 | if (ret) | 276 | if (ret) |
| 277 | return ret; | 277 | return ret; |
| 278 | 278 | ||
| 279 | val &= pchan->error.status_mask; | 279 | if (val & pchan->error.status_mask) { |
| 280 | if (val) { | 280 | val &= pchan->error.preserve_mask; |
| 281 | val &= ~pchan->error.status_mask; | ||
| 282 | pcc_chan_reg_write(&pchan->error, val); | 281 | pcc_chan_reg_write(&pchan->error, val); |
| 283 | return -EIO; | 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 | ret = pcc_chan_reg_init(&pchan->error, | 745 | ret = pcc_chan_reg_init(&pchan->error, |
| 747 | &pcct_ext->error_status_register, | 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 | "Error Status"); | 749 | "Error Status"); |
| 750 | } | 750 | } |
| 751 | return ret; | 751 | return ret; |
| @@ -77,6 +77,16 @@ struct cmdq_pkt { · 76 unmodified lines | |||
| 77 | size_t buf_size; /* real buffer size */ | 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 | u8 cmdq_get_shift_pa(struct mbox_chan *chan); | 90 | u8 cmdq_get_shift_pa(struct mbox_chan *chan); |
| 81 | 91 | ||
| 82 | #endif /* __MTK_CMDQ_MAILBOX_H__ */ | 92 | #endif /* __MTK_CMDQ_MAILBOX_H__ */ |