dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Lizhi Hou <lizhi.hou@amd.com>
To: "Mario Limonciello (AMD) (kernel.org)" <superm1@kernel.org>,
	<ogabbay@kernel.org>, <quic_jhugo@quicinc.com>,
	<dri-devel@lists.freedesktop.org>,
	<maciej.falkowski@linux.intel.com>
Cc: <linux-kernel@vger.kernel.org>, <max.zhen@amd.com>,
	<sonal.santan@amd.com>
Subject: Re: [PATCH V1] accel/amdxdna: Split mailbox channel create function
Date: Thu, 5 Mar 2026 09:28:32 -0800	[thread overview]
Message-ID: <387b4e61-a0b4-2da4-36e0-edbbb1870488@amd.com> (raw)
In-Reply-To: <21335ee2-4c88-4cf9-ad5a-00fb70c96f68@kernel.org>

Applied to drm-misc-fixes

On 3/5/26 07:48, Mario Limonciello (AMD) (kernel.org) wrote:
>
>
> On 3/5/2026 12:20 AM, Lizhi Hou wrote:
>> 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")
>> Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
> Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
>> ---
>>   drivers/accel/amdxdna/aie2_message.c    | 17 +++--
>>   drivers/accel/amdxdna/aie2_pci.c        | 63 ++++++++++-------
>>   drivers/accel/amdxdna/amdxdna_mailbox.c | 91 ++++++++++++-------------
>>   drivers/accel/amdxdna/amdxdna_mailbox.h | 31 +++++----
>>   4 files changed, 112 insertions(+), 90 deletions(-)
>>
>> diff --git a/drivers/accel/amdxdna/aie2_message.c 
>> b/drivers/accel/amdxdna/aie2_message.c
>> index 22e1a85a7ae0..ffcf3be79e23 100644
>> --- a/drivers/accel/amdxdna/aie2_message.c
>> +++ b/drivers/accel/amdxdna/aie2_message.c
>> @@ -293,13 +293,20 @@ int aie2_create_context(struct amdxdna_dev_hdl 
>> *ndev, struct amdxdna_hwctx *hwct
>>       }
>>         intr_reg = i2x.mb_head_ptr_reg + 4;
>> -    hwctx->priv->mbox_chann = 
>> xdna_mailbox_create_channel(ndev->mbox, &x2i, &i2x,
>> -                                  intr_reg, ret);
>> +    hwctx->priv->mbox_chann = xdna_mailbox_alloc_channel(ndev->mbox);
>>       if (!hwctx->priv->mbox_chann) {
>>           XDNA_ERR(xdna, "Not able to create channel");
>>           ret = -EINVAL;
>>           goto del_ctx_req;
>>       }
>> +
>> +    ret = xdna_mailbox_start_channel(hwctx->priv->mbox_chann, &x2i, 
>> &i2x,
>> +                     intr_reg, ret);
>> +    if (ret) {
>> +        XDNA_ERR(xdna, "Not able to create channel");
>> +        ret = -EINVAL;
>> +        goto free_channel;
>> +    }
>>       ndev->hwctx_num++;
>>         XDNA_DBG(xdna, "Mailbox channel irq: %d, msix_id: %d", ret, 
>> resp.msix_id);
>> @@ -307,6 +314,8 @@ int aie2_create_context(struct amdxdna_dev_hdl 
>> *ndev, struct amdxdna_hwctx *hwct
>>         return 0;
>>   +free_channel:
>> +    xdna_mailbox_free_channel(hwctx->priv->mbox_chann);
>>   del_ctx_req:
>>       aie2_destroy_context_req(ndev, hwctx->fw_ctx_id);
>>       return ret;
>> @@ -322,7 +331,7 @@ int aie2_destroy_context(struct amdxdna_dev_hdl 
>> *ndev, struct amdxdna_hwctx *hwc
>> xdna_mailbox_stop_channel(hwctx->priv->mbox_chann);
>>       ret = aie2_destroy_context_req(ndev, hwctx->fw_ctx_id);
>> - xdna_mailbox_destroy_channel(hwctx->priv->mbox_chann);
>> +    xdna_mailbox_free_channel(hwctx->priv->mbox_chann);
>>       XDNA_DBG(xdna, "Destroyed fw ctx %d", hwctx->fw_ctx_id);
>>       hwctx->priv->mbox_chann = NULL;
>>       hwctx->fw_ctx_id = -1;
>> @@ -921,7 +930,7 @@ void aie2_destroy_mgmt_chann(struct 
>> amdxdna_dev_hdl *ndev)
>>           return;
>>         xdna_mailbox_stop_channel(ndev->mgmt_chann);
>> -    xdna_mailbox_destroy_channel(ndev->mgmt_chann);
>> +    xdna_mailbox_free_channel(ndev->mgmt_chann);
>>       ndev->mgmt_chann = NULL;
>>   }
>>   diff --git a/drivers/accel/amdxdna/aie2_pci.c 
>> b/drivers/accel/amdxdna/aie2_pci.c
>> index 977ce21eaf9f..4924a9da55b6 100644
>> --- a/drivers/accel/amdxdna/aie2_pci.c
>> +++ b/drivers/accel/amdxdna/aie2_pci.c
>> @@ -361,10 +361,29 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
>>       }
>>       pci_set_master(pdev);
>>   +    mbox_res.ringbuf_base = ndev->sram_base;
>> +    mbox_res.ringbuf_size = pci_resource_len(pdev, 
>> xdna->dev_info->sram_bar);
>> +    mbox_res.mbox_base = ndev->mbox_base;
>> +    mbox_res.mbox_size = MBOX_SIZE(ndev);
>> +    mbox_res.name = "xdna_mailbox";
>> +    ndev->mbox = xdnam_mailbox_create(&xdna->ddev, &mbox_res);
>> +    if (!ndev->mbox) {
>> +        XDNA_ERR(xdna, "failed to create mailbox device");
>> +        ret = -ENODEV;
>> +        goto disable_dev;
>> +    }
>> +
>> +    ndev->mgmt_chann = xdna_mailbox_alloc_channel(ndev->mbox);
>> +    if (!ndev->mgmt_chann) {
>> +        XDNA_ERR(xdna, "failed to alloc channel");
>> +        ret = -ENODEV;
>> +        goto disable_dev;
>> +    }
>> +
>>       ret = aie2_smu_init(ndev);
>>       if (ret) {
>>           XDNA_ERR(xdna, "failed to init smu, ret %d", ret);
>> -        goto disable_dev;
>> +        goto free_channel;
>>       }
>>         ret = aie2_psp_start(ndev->psp_hdl);
>> @@ -379,18 +398,6 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
>>           goto stop_psp;
>>       }
>>   -    mbox_res.ringbuf_base = ndev->sram_base;
>> -    mbox_res.ringbuf_size = pci_resource_len(pdev, 
>> xdna->dev_info->sram_bar);
>> -    mbox_res.mbox_base = ndev->mbox_base;
>> -    mbox_res.mbox_size = MBOX_SIZE(ndev);
>> -    mbox_res.name = "xdna_mailbox";
>> -    ndev->mbox = xdnam_mailbox_create(&xdna->ddev, &mbox_res);
>> -    if (!ndev->mbox) {
>> -        XDNA_ERR(xdna, "failed to create mailbox device");
>> -        ret = -ENODEV;
>> -        goto stop_psp;
>> -    }
>> -
>>       mgmt_mb_irq = pci_irq_vector(pdev, ndev->mgmt_chan_idx);
>>       if (mgmt_mb_irq < 0) {
>>           ret = mgmt_mb_irq;
>> @@ -399,13 +406,13 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
>>       }
>>         xdna_mailbox_intr_reg = ndev->mgmt_i2x.mb_head_ptr_reg + 4;
>> -    ndev->mgmt_chann = xdna_mailbox_create_channel(ndev->mbox,
>> -                               &ndev->mgmt_x2i,
>> -                               &ndev->mgmt_i2x,
>> -                               xdna_mailbox_intr_reg,
>> -                               mgmt_mb_irq);
>> -    if (!ndev->mgmt_chann) {
>> -        XDNA_ERR(xdna, "failed to create management mailbox channel");
>> +    ret = xdna_mailbox_start_channel(ndev->mgmt_chann,
>> +                     &ndev->mgmt_x2i,
>> +                     &ndev->mgmt_i2x,
>> +                     xdna_mailbox_intr_reg,
>> +                     mgmt_mb_irq);
>> +    if (ret) {
>> +        XDNA_ERR(xdna, "failed to start management mailbox channel");
>>           ret = -EINVAL;
>>           goto stop_psp;
>>       }
>> @@ -413,37 +420,41 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
>>       ret = aie2_mgmt_fw_init(ndev);
>>       if (ret) {
>>           XDNA_ERR(xdna, "initial mgmt firmware failed, ret %d", ret);
>> -        goto destroy_mgmt_chann;
>> +        goto stop_fw;
>>       }
>>         ret = aie2_pm_init(ndev);
>>       if (ret) {
>>           XDNA_ERR(xdna, "failed to init pm, ret %d", ret);
>> -        goto destroy_mgmt_chann;
>> +        goto stop_fw;
>>       }
>>         ret = aie2_mgmt_fw_query(ndev);
>>       if (ret) {
>>           XDNA_ERR(xdna, "failed to query fw, ret %d", ret);
>> -        goto destroy_mgmt_chann;
>> +        goto stop_fw;
>>       }
>>         ret = aie2_error_async_events_alloc(ndev);
>>       if (ret) {
>>           XDNA_ERR(xdna, "Allocate async events failed, ret %d", ret);
>> -        goto destroy_mgmt_chann;
>> +        goto stop_fw;
>>       }
>>         ndev->dev_status = AIE2_DEV_START;
>>         return 0;
>>   -destroy_mgmt_chann:
>> -    aie2_destroy_mgmt_chann(ndev);
>> +stop_fw:
>> +    aie2_suspend_fw(ndev);
>> +    xdna_mailbox_stop_channel(ndev->mgmt_chann);
>>   stop_psp:
>>       aie2_psp_stop(ndev->psp_hdl);
>>   fini_smu:
>>       aie2_smu_fini(ndev);
>> +free_channel:
>> +    xdna_mailbox_free_channel(ndev->mgmt_chann);
>> +    ndev->mgmt_chann = NULL;
>>   disable_dev:
>>       pci_disable_device(pdev);
>>   diff --git a/drivers/accel/amdxdna/amdxdna_mailbox.c 
>> b/drivers/accel/amdxdna/amdxdna_mailbox.c
>> index 235a94047530..46d844a73a94 100644
>> --- a/drivers/accel/amdxdna/amdxdna_mailbox.c
>> +++ b/drivers/accel/amdxdna/amdxdna_mailbox.c
>> @@ -460,26 +460,49 @@ int xdna_mailbox_send_msg(struct 
>> mailbox_channel *mb_chann,
>>       return ret;
>>   }
>>   -struct mailbox_channel *
>> -xdna_mailbox_create_channel(struct mailbox *mb,
>> -                const struct xdna_mailbox_chann_res *x2i,
>> -                const struct xdna_mailbox_chann_res *i2x,
>> -                u32 iohub_int_addr,
>> -                int mb_irq)
>> +struct mailbox_channel *xdna_mailbox_alloc_channel(struct mailbox *mb)
>>   {
>>       struct mailbox_channel *mb_chann;
>> -    int ret;
>> -
>> -    if (!is_power_of_2(x2i->rb_size) || !is_power_of_2(i2x->rb_size)) {
>> -        pr_err("Ring buf size must be power of 2");
>> -        return NULL;
>> -    }
>>         mb_chann = kzalloc_obj(*mb_chann);
>>       if (!mb_chann)
>>           return NULL;
>>   +    INIT_WORK(&mb_chann->rx_work, mailbox_rx_worker);
>> +    mb_chann->work_q = create_singlethread_workqueue(MAILBOX_NAME);
>> +    if (!mb_chann->work_q) {
>> +        MB_ERR(mb_chann, "Create workqueue failed");
>> +        goto free_chann;
>> +    }
>>       mb_chann->mb = mb;
>> +
>> +    return mb_chann;
>> +
>> +free_chann:
>> +    kfree(mb_chann);
>> +    return NULL;
>> +}
>> +
>> +void xdna_mailbox_free_channel(struct mailbox_channel *mb_chann)
>> +{
>> +    destroy_workqueue(mb_chann->work_q);
>> +    kfree(mb_chann);
>> +}
>> +
>> +int
>> +xdna_mailbox_start_channel(struct mailbox_channel *mb_chann,
>> +               const struct xdna_mailbox_chann_res *x2i,
>> +               const struct xdna_mailbox_chann_res *i2x,
>> +               u32 iohub_int_addr,
>> +               int mb_irq)
>> +{
>> +    int ret;
>> +
>> +    if (!is_power_of_2(x2i->rb_size) || !is_power_of_2(i2x->rb_size)) {
>> +        pr_err("Ring buf size must be power of 2");
>> +        return -EINVAL;
>> +    }
>> +
>>       mb_chann->msix_irq = mb_irq;
>>       mb_chann->iohub_int_addr = iohub_int_addr;
>>       memcpy(&mb_chann->res[CHAN_RES_X2I], x2i, sizeof(*x2i));
>> @@ -489,61 +512,37 @@ xdna_mailbox_create_channel(struct mailbox *mb,
>>       mb_chann->x2i_tail = mailbox_get_tailptr(mb_chann, CHAN_RES_X2I);
>>       mb_chann->i2x_head = mailbox_get_headptr(mb_chann, CHAN_RES_I2X);
>>   -    INIT_WORK(&mb_chann->rx_work, mailbox_rx_worker);
>> -    mb_chann->work_q = create_singlethread_workqueue(MAILBOX_NAME);
>> -    if (!mb_chann->work_q) {
>> -        MB_ERR(mb_chann, "Create workqueue failed");
>> -        goto free_and_out;
>> -    }
>> -
>>       /* Everything look good. Time to enable irq handler */
>>       ret = request_irq(mb_irq, mailbox_irq_handler, 0, MAILBOX_NAME, 
>> mb_chann);
>>       if (ret) {
>>           MB_ERR(mb_chann, "Failed to request irq %d ret %d", mb_irq, 
>> ret);
>> -        goto destroy_wq;
>> +        return ret;
>>       }
>>         mb_chann->bad_state = false;
>>       mailbox_reg_write(mb_chann, mb_chann->iohub_int_addr, 0);
>>   -    MB_DBG(mb_chann, "Mailbox channel created (irq: %d)", 
>> mb_chann->msix_irq);
>> -    return mb_chann;
>> -
>> -destroy_wq:
>> -    destroy_workqueue(mb_chann->work_q);
>> -free_and_out:
>> -    kfree(mb_chann);
>> -    return NULL;
>> +    MB_DBG(mb_chann, "Mailbox channel started (irq: %d)", 
>> mb_chann->msix_irq);
>> +    return 0;
>>   }
>>   -int xdna_mailbox_destroy_channel(struct mailbox_channel *mb_chann)
>> +void xdna_mailbox_stop_channel(struct mailbox_channel *mb_chann)
>>   {
>>       struct mailbox_msg *mb_msg;
>>       unsigned long msg_id;
>>   -    MB_DBG(mb_chann, "IRQ disabled and RX work cancelled");
>> +    /* Disable an irq and wait. This might sleep. */
>>       free_irq(mb_chann->msix_irq, mb_chann);
>> -    destroy_workqueue(mb_chann->work_q);
>> -    /* We can clean up and release resources */
>>   +    /* Cancel RX work and wait for it to finish */
>> +    drain_workqueue(mb_chann->work_q);
>> +
>> +    /* We can clean up and release resources */
>>       xa_for_each(&mb_chann->chan_xa, msg_id, mb_msg)
>>           mailbox_release_msg(mb_chann, mb_msg);
>> -
>>       xa_destroy(&mb_chann->chan_xa);
>>   -    MB_DBG(mb_chann, "Mailbox channel destroyed, irq: %d", 
>> mb_chann->msix_irq);
>> -    kfree(mb_chann);
>> -    return 0;
>> -}
>> -
>> -void xdna_mailbox_stop_channel(struct mailbox_channel *mb_chann)
>> -{
>> -    /* Disable an irq and wait. This might sleep. */
>> -    disable_irq(mb_chann->msix_irq);
>> -
>> -    /* Cancel RX work and wait for it to finish */
>> -    cancel_work_sync(&mb_chann->rx_work);
>> -    MB_DBG(mb_chann, "IRQ disabled and RX work cancelled");
>> +    MB_DBG(mb_chann, "Mailbox channel stopped, irq: %d", 
>> mb_chann->msix_irq);
>>   }
>>     struct mailbox *xdnam_mailbox_create(struct drm_device *ddev,
>> diff --git a/drivers/accel/amdxdna/amdxdna_mailbox.h 
>> b/drivers/accel/amdxdna/amdxdna_mailbox.h
>> index ea367f2fb738..8b1e00945da4 100644
>> --- a/drivers/accel/amdxdna/amdxdna_mailbox.h
>> +++ b/drivers/accel/amdxdna/amdxdna_mailbox.h
>> @@ -74,9 +74,16 @@ struct mailbox *xdnam_mailbox_create(struct 
>> drm_device *ddev,
>>                        const struct xdna_mailbox_res *res);
>>     /*
>> - * xdna_mailbox_create_channel() -- Create a mailbox channel instance
>> + * xdna_mailbox_alloc_channel() -- alloc a mailbox channel
>>    *
>> - * @mailbox: the handle return from xdna_mailbox_create()
>> + * @mb: mailbox handle
>> + */
>> +struct mailbox_channel *xdna_mailbox_alloc_channel(struct mailbox *mb);
>> +
>> +/*
>> + * xdna_mailbox_start_channel() -- start a mailbox channel instance
>> + *
>> + * @mb_chann: the handle return from xdna_mailbox_alloc_channel()
>>    * @x2i: host to firmware mailbox resources
>>    * @i2x: firmware to host mailbox resources
>>    * @xdna_mailbox_intr_reg: register addr of MSI-X interrupt
>> @@ -84,28 +91,24 @@ struct mailbox *xdnam_mailbox_create(struct 
>> drm_device *ddev,
>>    *
>>    * Return: If success, return a handle of mailbox channel. 
>> Otherwise, return NULL.
>>    */
>> -struct mailbox_channel *
>> -xdna_mailbox_create_channel(struct mailbox *mailbox,
>> -                const struct xdna_mailbox_chann_res *x2i,
>> -                const struct xdna_mailbox_chann_res *i2x,
>> -                u32 xdna_mailbox_intr_reg,
>> -                int mb_irq);
>> +int
>> +xdna_mailbox_start_channel(struct mailbox_channel *mb_chann,
>> +               const struct xdna_mailbox_chann_res *x2i,
>> +               const struct xdna_mailbox_chann_res *i2x,
>> +               u32 xdna_mailbox_intr_reg,
>> +               int mb_irq);
>>     /*
>> - * xdna_mailbox_destroy_channel() -- destroy mailbox channel
>> + * xdna_mailbox_free_channel() -- free mailbox channel
>>    *
>>    * @mailbox_chann: the handle return from 
>> xdna_mailbox_create_channel()
>> - *
>> - * Return: if success, return 0. otherwise return error code
>>    */
>> -int xdna_mailbox_destroy_channel(struct mailbox_channel 
>> *mailbox_chann);
>> +void xdna_mailbox_free_channel(struct mailbox_channel *mailbox_chann);
>>     /*
>>    * xdna_mailbox_stop_channel() -- stop mailbox channel
>>    *
>>    * @mailbox_chann: the handle return from 
>> xdna_mailbox_create_channel()
>> - *
>> - * Return: if success, return 0. otherwise return error code
>>    */
>>   void xdna_mailbox_stop_channel(struct mailbox_channel *mailbox_chann);
>

      reply	other threads:[~2026-03-05 17:28 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-05  6:20 [PATCH V1] accel/amdxdna: Split mailbox channel create function Lizhi Hou
2026-03-05 15:48 ` Mario Limonciello (AMD) (kernel.org)
2026-03-05 17:28   ` Lizhi Hou [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=387b4e61-a0b4-2da4-36e0-edbbb1870488@amd.com \
    --to=lizhi.hou@amd.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maciej.falkowski@linux.intel.com \
    --cc=max.zhen@amd.com \
    --cc=ogabbay@kernel.org \
    --cc=quic_jhugo@quicinc.com \
    --cc=sonal.santan@amd.com \
    --cc=superm1@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox