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.

accel/amdxdna: Split mailbox channel create function

The management channel used for firmware control command submission is
currently created after the firmware is started. If channel creation
fails (for example, due to memory allocation failure or workqueue
creation interruption), the firmware remains in a pending state and is
unable to receive any control commands.

To avoid leaving the firmware in this inconsistent state, split
xdna_mailbox_create_channel() into two separate functions so that
resource allocation can be completed before interacting with the
hardware.
xdna_mailbox_alloc_channel()
Allocates memory and initializes the workqueue. This can be called
earlier, before interacting with the hardware.
xdna_mailbox_start_channel()
Performs the hardware interaction required to start the channel.

Rename xdna_mailbox_destroy_channel() to xdna_mailbox_free_channel().
Ensure that xdna_mailbox_stop_channel() and xdna_mailbox_free_channel()
properly unwind the corresponding start and allocation steps, respectively.

Fixes: b87f920b9344 ("accel/amdxdna: Support hardware mailbox")
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Link: https://patch.msgid.link/20260305062041.3954024-1-lizhi.hou@amd.com

Lizhi Hou d5b8b034 76e8173b

+116 -94
+13 -4
drivers/accel/amdxdna/aie2_message.c
··· 293 293 } 294 294 295 295 intr_reg = i2x.mb_head_ptr_reg + 4; 296 - hwctx->priv->mbox_chann = xdna_mailbox_create_channel(ndev->mbox, &x2i, &i2x, 297 - intr_reg, ret); 296 + hwctx->priv->mbox_chann = xdna_mailbox_alloc_channel(ndev->mbox); 298 297 if (!hwctx->priv->mbox_chann) { 299 298 XDNA_ERR(xdna, "Not able to create channel"); 300 299 ret = -EINVAL; 301 300 goto del_ctx_req; 301 + } 302 + 303 + ret = xdna_mailbox_start_channel(hwctx->priv->mbox_chann, &x2i, &i2x, 304 + intr_reg, ret); 305 + if (ret) { 306 + XDNA_ERR(xdna, "Not able to create channel"); 307 + ret = -EINVAL; 308 + goto free_channel; 302 309 } 303 310 ndev->hwctx_num++; 304 311 ··· 314 307 315 308 return 0; 316 309 310 + free_channel: 311 + xdna_mailbox_free_channel(hwctx->priv->mbox_chann); 317 312 del_ctx_req: 318 313 aie2_destroy_context_req(ndev, hwctx->fw_ctx_id); 319 314 return ret; ··· 331 322 332 323 xdna_mailbox_stop_channel(hwctx->priv->mbox_chann); 333 324 ret = aie2_destroy_context_req(ndev, hwctx->fw_ctx_id); 334 - xdna_mailbox_destroy_channel(hwctx->priv->mbox_chann); 325 + xdna_mailbox_free_channel(hwctx->priv->mbox_chann); 335 326 XDNA_DBG(xdna, "Destroyed fw ctx %d", hwctx->fw_ctx_id); 336 327 hwctx->priv->mbox_chann = NULL; 337 328 hwctx->fw_ctx_id = -1; ··· 930 921 return; 931 922 932 923 xdna_mailbox_stop_channel(ndev->mgmt_chann); 933 - xdna_mailbox_destroy_channel(ndev->mgmt_chann); 924 + xdna_mailbox_free_channel(ndev->mgmt_chann); 934 925 ndev->mgmt_chann = NULL; 935 926 } 936 927
+37 -26
drivers/accel/amdxdna/aie2_pci.c
··· 361 361 } 362 362 pci_set_master(pdev); 363 363 364 + mbox_res.ringbuf_base = ndev->sram_base; 365 + mbox_res.ringbuf_size = pci_resource_len(pdev, xdna->dev_info->sram_bar); 366 + mbox_res.mbox_base = ndev->mbox_base; 367 + mbox_res.mbox_size = MBOX_SIZE(ndev); 368 + mbox_res.name = "xdna_mailbox"; 369 + ndev->mbox = xdnam_mailbox_create(&xdna->ddev, &mbox_res); 370 + if (!ndev->mbox) { 371 + XDNA_ERR(xdna, "failed to create mailbox device"); 372 + ret = -ENODEV; 373 + goto disable_dev; 374 + } 375 + 376 + ndev->mgmt_chann = xdna_mailbox_alloc_channel(ndev->mbox); 377 + if (!ndev->mgmt_chann) { 378 + XDNA_ERR(xdna, "failed to alloc channel"); 379 + ret = -ENODEV; 380 + goto disable_dev; 381 + } 382 + 364 383 ret = aie2_smu_init(ndev); 365 384 if (ret) { 366 385 XDNA_ERR(xdna, "failed to init smu, ret %d", ret); 367 - goto disable_dev; 386 + goto free_channel; 368 387 } 369 388 370 389 ret = aie2_psp_start(ndev->psp_hdl); ··· 398 379 goto stop_psp; 399 380 } 400 381 401 - mbox_res.ringbuf_base = ndev->sram_base; 402 - mbox_res.ringbuf_size = pci_resource_len(pdev, xdna->dev_info->sram_bar); 403 - mbox_res.mbox_base = ndev->mbox_base; 404 - mbox_res.mbox_size = MBOX_SIZE(ndev); 405 - mbox_res.name = "xdna_mailbox"; 406 - ndev->mbox = xdnam_mailbox_create(&xdna->ddev, &mbox_res); 407 - if (!ndev->mbox) { 408 - XDNA_ERR(xdna, "failed to create mailbox device"); 409 - ret = -ENODEV; 410 - goto stop_psp; 411 - } 412 - 413 382 mgmt_mb_irq = pci_irq_vector(pdev, ndev->mgmt_chan_idx); 414 383 if (mgmt_mb_irq < 0) { 415 384 ret = mgmt_mb_irq; ··· 406 399 } 407 400 408 401 xdna_mailbox_intr_reg = ndev->mgmt_i2x.mb_head_ptr_reg + 4; 409 - ndev->mgmt_chann = xdna_mailbox_create_channel(ndev->mbox, 410 - &ndev->mgmt_x2i, 411 - &ndev->mgmt_i2x, 412 - xdna_mailbox_intr_reg, 413 - mgmt_mb_irq); 414 - if (!ndev->mgmt_chann) { 415 - XDNA_ERR(xdna, "failed to create management mailbox channel"); 402 + ret = xdna_mailbox_start_channel(ndev->mgmt_chann, 403 + &ndev->mgmt_x2i, 404 + &ndev->mgmt_i2x, 405 + xdna_mailbox_intr_reg, 406 + mgmt_mb_irq); 407 + if (ret) { 408 + XDNA_ERR(xdna, "failed to start management mailbox channel"); 416 409 ret = -EINVAL; 417 410 goto stop_psp; 418 411 } ··· 420 413 ret = aie2_mgmt_fw_init(ndev); 421 414 if (ret) { 422 415 XDNA_ERR(xdna, "initial mgmt firmware failed, ret %d", ret); 423 - goto destroy_mgmt_chann; 416 + goto stop_fw; 424 417 } 425 418 426 419 ret = aie2_pm_init(ndev); 427 420 if (ret) { 428 421 XDNA_ERR(xdna, "failed to init pm, ret %d", ret); 429 - goto destroy_mgmt_chann; 422 + goto stop_fw; 430 423 } 431 424 432 425 ret = aie2_mgmt_fw_query(ndev); 433 426 if (ret) { 434 427 XDNA_ERR(xdna, "failed to query fw, ret %d", ret); 435 - goto destroy_mgmt_chann; 428 + goto stop_fw; 436 429 } 437 430 438 431 ret = aie2_error_async_events_alloc(ndev); 439 432 if (ret) { 440 433 XDNA_ERR(xdna, "Allocate async events failed, ret %d", ret); 441 - goto destroy_mgmt_chann; 434 + goto stop_fw; 442 435 } 443 436 444 437 ndev->dev_status = AIE2_DEV_START; 445 438 446 439 return 0; 447 440 448 - destroy_mgmt_chann: 449 - aie2_destroy_mgmt_chann(ndev); 441 + stop_fw: 442 + aie2_suspend_fw(ndev); 443 + xdna_mailbox_stop_channel(ndev->mgmt_chann); 450 444 stop_psp: 451 445 aie2_psp_stop(ndev->psp_hdl); 452 446 fini_smu: 453 447 aie2_smu_fini(ndev); 448 + free_channel: 449 + xdna_mailbox_free_channel(ndev->mgmt_chann); 450 + ndev->mgmt_chann = NULL; 454 451 disable_dev: 455 452 pci_disable_device(pdev); 456 453
+49 -50
drivers/accel/amdxdna/amdxdna_mailbox.c
··· 460 460 return ret; 461 461 } 462 462 463 - struct mailbox_channel * 464 - xdna_mailbox_create_channel(struct mailbox *mb, 465 - const struct xdna_mailbox_chann_res *x2i, 466 - const struct xdna_mailbox_chann_res *i2x, 467 - u32 iohub_int_addr, 468 - int mb_irq) 463 + struct mailbox_channel *xdna_mailbox_alloc_channel(struct mailbox *mb) 469 464 { 470 465 struct mailbox_channel *mb_chann; 471 - int ret; 472 - 473 - if (!is_power_of_2(x2i->rb_size) || !is_power_of_2(i2x->rb_size)) { 474 - pr_err("Ring buf size must be power of 2"); 475 - return NULL; 476 - } 477 466 478 467 mb_chann = kzalloc_obj(*mb_chann); 479 468 if (!mb_chann) 480 469 return NULL; 481 470 471 + INIT_WORK(&mb_chann->rx_work, mailbox_rx_worker); 472 + mb_chann->work_q = create_singlethread_workqueue(MAILBOX_NAME); 473 + if (!mb_chann->work_q) { 474 + MB_ERR(mb_chann, "Create workqueue failed"); 475 + goto free_chann; 476 + } 482 477 mb_chann->mb = mb; 478 + 479 + return mb_chann; 480 + 481 + free_chann: 482 + kfree(mb_chann); 483 + return NULL; 484 + } 485 + 486 + void xdna_mailbox_free_channel(struct mailbox_channel *mb_chann) 487 + { 488 + destroy_workqueue(mb_chann->work_q); 489 + kfree(mb_chann); 490 + } 491 + 492 + int 493 + xdna_mailbox_start_channel(struct mailbox_channel *mb_chann, 494 + const struct xdna_mailbox_chann_res *x2i, 495 + const struct xdna_mailbox_chann_res *i2x, 496 + u32 iohub_int_addr, 497 + int mb_irq) 498 + { 499 + int ret; 500 + 501 + if (!is_power_of_2(x2i->rb_size) || !is_power_of_2(i2x->rb_size)) { 502 + pr_err("Ring buf size must be power of 2"); 503 + return -EINVAL; 504 + } 505 + 483 506 mb_chann->msix_irq = mb_irq; 484 507 mb_chann->iohub_int_addr = iohub_int_addr; 485 508 memcpy(&mb_chann->res[CHAN_RES_X2I], x2i, sizeof(*x2i)); ··· 512 489 mb_chann->x2i_tail = mailbox_get_tailptr(mb_chann, CHAN_RES_X2I); 513 490 mb_chann->i2x_head = mailbox_get_headptr(mb_chann, CHAN_RES_I2X); 514 491 515 - INIT_WORK(&mb_chann->rx_work, mailbox_rx_worker); 516 - mb_chann->work_q = create_singlethread_workqueue(MAILBOX_NAME); 517 - if (!mb_chann->work_q) { 518 - MB_ERR(mb_chann, "Create workqueue failed"); 519 - goto free_and_out; 520 - } 521 - 522 492 /* Everything look good. Time to enable irq handler */ 523 493 ret = request_irq(mb_irq, mailbox_irq_handler, 0, MAILBOX_NAME, mb_chann); 524 494 if (ret) { 525 495 MB_ERR(mb_chann, "Failed to request irq %d ret %d", mb_irq, ret); 526 - goto destroy_wq; 496 + return ret; 527 497 } 528 498 529 499 mb_chann->bad_state = false; 530 500 mailbox_reg_write(mb_chann, mb_chann->iohub_int_addr, 0); 531 501 532 - MB_DBG(mb_chann, "Mailbox channel created (irq: %d)", mb_chann->msix_irq); 533 - return mb_chann; 534 - 535 - destroy_wq: 536 - destroy_workqueue(mb_chann->work_q); 537 - free_and_out: 538 - kfree(mb_chann); 539 - return NULL; 540 - } 541 - 542 - int xdna_mailbox_destroy_channel(struct mailbox_channel *mb_chann) 543 - { 544 - struct mailbox_msg *mb_msg; 545 - unsigned long msg_id; 546 - 547 - MB_DBG(mb_chann, "IRQ disabled and RX work cancelled"); 548 - free_irq(mb_chann->msix_irq, mb_chann); 549 - destroy_workqueue(mb_chann->work_q); 550 - /* We can clean up and release resources */ 551 - 552 - xa_for_each(&mb_chann->chan_xa, msg_id, mb_msg) 553 - mailbox_release_msg(mb_chann, mb_msg); 554 - 555 - xa_destroy(&mb_chann->chan_xa); 556 - 557 - MB_DBG(mb_chann, "Mailbox channel destroyed, irq: %d", mb_chann->msix_irq); 558 - kfree(mb_chann); 502 + MB_DBG(mb_chann, "Mailbox channel started (irq: %d)", mb_chann->msix_irq); 559 503 return 0; 560 504 } 561 505 562 506 void xdna_mailbox_stop_channel(struct mailbox_channel *mb_chann) 563 507 { 508 + struct mailbox_msg *mb_msg; 509 + unsigned long msg_id; 510 + 564 511 /* Disable an irq and wait. This might sleep. */ 565 - disable_irq(mb_chann->msix_irq); 512 + free_irq(mb_chann->msix_irq, mb_chann); 566 513 567 514 /* Cancel RX work and wait for it to finish */ 568 - cancel_work_sync(&mb_chann->rx_work); 569 - MB_DBG(mb_chann, "IRQ disabled and RX work cancelled"); 515 + drain_workqueue(mb_chann->work_q); 516 + 517 + /* We can clean up and release resources */ 518 + xa_for_each(&mb_chann->chan_xa, msg_id, mb_msg) 519 + mailbox_release_msg(mb_chann, mb_msg); 520 + xa_destroy(&mb_chann->chan_xa); 521 + 522 + MB_DBG(mb_chann, "Mailbox channel stopped, irq: %d", mb_chann->msix_irq); 570 523 } 571 524 572 525 struct mailbox *xdnam_mailbox_create(struct drm_device *ddev,
+17 -14
drivers/accel/amdxdna/amdxdna_mailbox.h
··· 74 74 const struct xdna_mailbox_res *res); 75 75 76 76 /* 77 - * xdna_mailbox_create_channel() -- Create a mailbox channel instance 77 + * xdna_mailbox_alloc_channel() -- alloc a mailbox channel 78 78 * 79 - * @mailbox: the handle return from xdna_mailbox_create() 79 + * @mb: mailbox handle 80 + */ 81 + struct mailbox_channel *xdna_mailbox_alloc_channel(struct mailbox *mb); 82 + 83 + /* 84 + * xdna_mailbox_start_channel() -- start a mailbox channel instance 85 + * 86 + * @mb_chann: the handle return from xdna_mailbox_alloc_channel() 80 87 * @x2i: host to firmware mailbox resources 81 88 * @i2x: firmware to host mailbox resources 82 89 * @xdna_mailbox_intr_reg: register addr of MSI-X interrupt ··· 91 84 * 92 85 * Return: If success, return a handle of mailbox channel. Otherwise, return NULL. 93 86 */ 94 - struct mailbox_channel * 95 - xdna_mailbox_create_channel(struct mailbox *mailbox, 96 - const struct xdna_mailbox_chann_res *x2i, 97 - const struct xdna_mailbox_chann_res *i2x, 98 - u32 xdna_mailbox_intr_reg, 99 - int mb_irq); 87 + int 88 + xdna_mailbox_start_channel(struct mailbox_channel *mb_chann, 89 + const struct xdna_mailbox_chann_res *x2i, 90 + const struct xdna_mailbox_chann_res *i2x, 91 + u32 xdna_mailbox_intr_reg, 92 + int mb_irq); 100 93 101 94 /* 102 - * xdna_mailbox_destroy_channel() -- destroy mailbox channel 95 + * xdna_mailbox_free_channel() -- free mailbox channel 103 96 * 104 97 * @mailbox_chann: the handle return from xdna_mailbox_create_channel() 105 - * 106 - * Return: if success, return 0. otherwise return error code 107 98 */ 108 - int xdna_mailbox_destroy_channel(struct mailbox_channel *mailbox_chann); 99 + void xdna_mailbox_free_channel(struct mailbox_channel *mailbox_chann); 109 100 110 101 /* 111 102 * xdna_mailbox_stop_channel() -- stop mailbox channel 112 103 * 113 104 * @mailbox_chann: the handle return from xdna_mailbox_create_channel() 114 - * 115 - * Return: if success, return 0. otherwise return error code 116 105 */ 117 106 void xdna_mailbox_stop_channel(struct mailbox_channel *mailbox_chann); 118 107