Merge tag 'mailbox-v7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox

Pull mailbox updates from Jassi Brar:

 - core: fix NULL message handling and add API to query TX queue slots

 - test: resolve concurrency bugs, dangling IRQs, and memory leaks

 - dt-bindings: qcom: add Eliza IPCC

 - mtk: fix address calculation and pointer handling bugs

 - cix: resolve SCMI suspend timeouts

 - misc memory allocation optimizations and cleanups

* tag 'mailbox-v7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox:
  mailbox: mailbox-test: make data_ready a per-instance variable
  mailbox: mailbox-test: initialize struct earlier
  mailbox: mailbox-test: don't free the reused channel
  mailbox: mailbox-test: handle channel errors consistently
  mailbox: update kdoc for struct mbox_controller
  mailbox: add sanity check for channel array
  mailbox: mailbox-test: free channels on probe error
  mailbox: prefix new constants with MBOX_
  dt-bindings: mailbox: qcom-ipcc: Document the Eliza Inter-Processor Communication Controller
  mailbox: cix: Add IRQF_NO_SUSPEND to mailbox interrupt
  mailbox: Fix NULL message support in mbox_send_message()
  mailbox: remove superfluous internal header
  mailbox: correct kdoc title for mbox_bind_client
  mailbox: test: really ignore optional memory resources
  mailbox: exynos: drop superfluous mbox setting per channel
  mailbox: mtk-cmdq: Fix CURR and END addr for task insert case
  mailbox: mtk-vcp-mailbox: Fix the return value in mtk_vcp_mbox_xlate()
  mailbox: hi6220: kzalloc + kcalloc to kzalloc
  mailbox: rockchip: kzalloc + kcalloc to kzalloc
  mailbox: add API to query available TX queue slots
This commit is contained in:
Linus Torvalds
2026-04-27 15:21:18 -07:00
18 changed files with 124 additions and 119 deletions

View File

@@ -24,6 +24,7 @@ properties:
compatible:
items:
- enum:
- qcom,eliza-ipcc
- qcom,glymur-ipcc
- qcom,kaanapali-ipcc
- qcom,milos-ipcc

View File

@@ -12,8 +12,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include "mailbox.h"
/*
* The maximum transmission size is 32 words or 128 bytes.
*/
@@ -405,7 +403,7 @@ static int cix_mbox_startup(struct mbox_chan *chan)
int index = cp->index, ret;
u32 val;
ret = request_irq(priv->irq, cix_mbox_isr, 0,
ret = request_irq(priv->irq, cix_mbox_isr, IRQF_NO_SUSPEND,
dev_name(priv->dev), chan);
if (ret) {
dev_err(priv->dev, "Unable to acquire IRQ %d\n", priv->irq);
@@ -415,7 +413,7 @@ static int cix_mbox_startup(struct mbox_chan *chan)
switch (cp->type) {
case CIX_MBOX_TYPE_DB:
/* Overwrite txdone_method for DB channel */
chan->txdone_method = TXDONE_BY_ACK;
chan->txdone_method = MBOX_TXDONE_BY_ACK;
fallthrough;
case CIX_MBOX_TYPE_REG:
if (priv->dir == CIX_MBOX_TX) {

View File

@@ -99,7 +99,6 @@ static int exynos_mbox_probe(struct platform_device *pdev)
struct mbox_controller *mbox;
struct mbox_chan *chans;
struct clk *pclk;
int i;
exynos_mbox = devm_kzalloc(dev, sizeof(*exynos_mbox), GFP_KERNEL);
if (!exynos_mbox)
@@ -129,9 +128,6 @@ static int exynos_mbox_probe(struct platform_device *pdev)
mbox->ops = &exynos_mbox_chan_ops;
mbox->of_xlate = exynos_mbox_of_xlate;
for (i = 0; i < EXYNOS_MBOX_CHAN_COUNT; i++)
chans[i].mbox = mbox;
exynos_mbox->mbox = mbox;
platform_set_drvdata(pdev, exynos_mbox);

View File

@@ -15,8 +15,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include "mailbox.h"
#define MBOX_CHAN_MAX 32
#define MBOX_RX 0x0

View File

@@ -79,12 +79,12 @@ struct hi6220_mbox {
/* region for mailbox */
void __iomem *base;
unsigned int chan_num;
struct hi6220_mbox_chan *mchan;
void *irq_map_chan[MBOX_CHAN_MAX];
struct mbox_chan *chan;
struct mbox_controller controller;
unsigned int chan_num;
struct hi6220_mbox_chan mchan[] __counted_by(chan_num);
};
static void mbox_set_state(struct hi6220_mbox *mbox,
@@ -267,16 +267,12 @@ static int hi6220_mbox_probe(struct platform_device *pdev)
struct hi6220_mbox *mbox;
int i, err;
mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
mbox = devm_kzalloc(dev, struct_size(mbox, mchan, MBOX_CHAN_MAX), GFP_KERNEL);
if (!mbox)
return -ENOMEM;
mbox->dev = dev;
mbox->chan_num = MBOX_CHAN_MAX;
mbox->mchan = devm_kcalloc(dev,
mbox->chan_num, sizeof(*mbox->mchan), GFP_KERNEL);
if (!mbox->mchan)
return -ENOMEM;
mbox->dev = dev;
mbox->chan = devm_kcalloc(dev,
mbox->chan_num, sizeof(*mbox->chan), GFP_KERNEL);

View File

@@ -23,8 +23,6 @@
#include <linux/slab.h>
#include <linux/workqueue.h>
#include "mailbox.h"
#define IMX_MU_CHANS 24
/* TX0/RX0/RXDB[0-3] */
#define IMX_MU_SCU_CHANS 6
@@ -734,7 +732,7 @@ static struct mbox_chan * imx_mu_xlate(struct mbox_controller *mbox,
p_chan = &mbox->chans[chan];
if (type == IMX_MU_TYPE_TXDB_V2)
p_chan->txdone_method = TXDONE_BY_ACK;
p_chan->txdone_method = MBOX_TXDONE_BY_ACK;
return p_chan;
}

View File

@@ -21,8 +21,6 @@
#include <linux/property.h>
#include <linux/slab.h>
#include "mailbox.h"
#define STI_MBOX_INST_MAX 4 /* RAM saving: Max supported instances */
#define STI_MBOX_CHAN_MAX 20 /* RAM saving: Max supported channels */

View File

@@ -28,8 +28,6 @@
#define MBOX_HEXDUMP_MAX_LEN (MBOX_HEXDUMP_LINE_LEN * \
(MBOX_MAX_MSG_LEN / MBOX_BYTES_PER_LINE))
static bool mbox_data_ready;
struct mbox_test_device {
struct device *dev;
void __iomem *tx_mmio;
@@ -42,6 +40,7 @@ struct mbox_test_device {
spinlock_t lock;
struct mutex mutex;
wait_queue_head_t waitq;
bool data_ready;
struct fasync_struct *async_queue;
struct dentry *root_debugfs_dir;
};
@@ -162,7 +161,7 @@ static bool mbox_test_message_data_ready(struct mbox_test_device *tdev)
unsigned long flags;
spin_lock_irqsave(&tdev->lock, flags);
data_ready = mbox_data_ready;
data_ready = tdev->data_ready;
spin_unlock_irqrestore(&tdev->lock, flags);
return data_ready;
@@ -227,7 +226,7 @@ static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf,
*(touser + l) = '\0';
memset(tdev->rx_buffer, 0, MBOX_MAX_MSG_LEN);
mbox_data_ready = false;
tdev->data_ready = false;
spin_unlock_irqrestore(&tdev->lock, flags);
@@ -297,7 +296,7 @@ static void mbox_test_receive_message(struct mbox_client *client, void *message)
message, MBOX_MAX_MSG_LEN);
memcpy(tdev->rx_buffer, message, MBOX_MAX_MSG_LEN);
}
mbox_data_ready = true;
tdev->data_ready = true;
spin_unlock_irqrestore(&tdev->lock, flags);
wake_up_interruptible(&tdev->waitq);
@@ -336,7 +335,7 @@ mbox_test_request_channel(struct platform_device *pdev, const char *name)
client = devm_kzalloc(&pdev->dev, sizeof(*client), GFP_KERNEL);
if (!client)
return ERR_PTR(-ENOMEM);
return NULL;
client->dev = &pdev->dev;
client->rx_callback = mbox_test_receive_message;
@@ -355,67 +354,80 @@ mbox_test_request_channel(struct platform_device *pdev, const char *name)
return channel;
}
static void __iomem *mbox_test_ioremap(struct platform_device *pdev, unsigned int res_num)
{
struct resource *res;
void __iomem *mmio;
res = platform_get_resource(pdev, IORESOURCE_MEM, res_num);
if (!res)
return NULL;
mmio = devm_ioremap_resource(&pdev->dev, res);
if (PTR_ERR(mmio) == -EBUSY) {
dev_info(&pdev->dev, "trying workaround with plain ioremap\n");
return devm_ioremap(&pdev->dev, res->start, resource_size(res));
}
return IS_ERR(mmio) ? NULL : mmio;
}
static int mbox_test_probe(struct platform_device *pdev)
{
struct mbox_test_device *tdev;
struct resource *res;
resource_size_t size;
int ret;
tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
if (!tdev)
return -ENOMEM;
tdev->dev = &pdev->dev;
spin_lock_init(&tdev->lock);
mutex_init(&tdev->mutex);
init_waitqueue_head(&tdev->waitq);
platform_set_drvdata(pdev, tdev);
/* It's okay for MMIO to be NULL */
tdev->tx_mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (PTR_ERR(tdev->tx_mmio) == -EBUSY) {
/* if reserved area in SRAM, try just ioremap */
size = resource_size(res);
tdev->tx_mmio = devm_ioremap(&pdev->dev, res->start, size);
} else if (IS_ERR(tdev->tx_mmio)) {
tdev->tx_mmio = NULL;
}
tdev->tx_mmio = mbox_test_ioremap(pdev, 0);
/* If specified, second reg entry is Rx MMIO */
tdev->rx_mmio = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
if (PTR_ERR(tdev->rx_mmio) == -EBUSY) {
size = resource_size(res);
tdev->rx_mmio = devm_ioremap(&pdev->dev, res->start, size);
} else if (IS_ERR(tdev->rx_mmio)) {
tdev->rx_mmio = mbox_test_ioremap(pdev, 1);
if (!tdev->rx_mmio)
tdev->rx_mmio = tdev->tx_mmio;
}
tdev->tx_channel = mbox_test_request_channel(pdev, "tx");
tdev->rx_channel = mbox_test_request_channel(pdev, "rx");
if (IS_ERR_OR_NULL(tdev->tx_channel) && IS_ERR_OR_NULL(tdev->rx_channel))
if (!tdev->tx_channel && !tdev->rx_channel)
return -EPROBE_DEFER;
/* If Rx is not specified but has Rx MMIO, then Rx = Tx */
if (!tdev->rx_channel && (tdev->rx_mmio != tdev->tx_mmio))
tdev->rx_channel = tdev->tx_channel;
tdev->dev = &pdev->dev;
platform_set_drvdata(pdev, tdev);
spin_lock_init(&tdev->lock);
mutex_init(&tdev->mutex);
if (tdev->rx_channel) {
tdev->rx_buffer = devm_kzalloc(&pdev->dev,
MBOX_MAX_MSG_LEN, GFP_KERNEL);
if (!tdev->rx_buffer)
return -ENOMEM;
if (!tdev->rx_buffer) {
ret = -ENOMEM;
goto err_free_chans;
}
}
ret = mbox_test_add_debugfs(pdev, tdev);
if (ret)
return ret;
goto err_free_chans;
init_waitqueue_head(&tdev->waitq);
dev_info(&pdev->dev, "Successfully registered\n");
return 0;
err_free_chans:
if (tdev->tx_channel)
mbox_free_channel(tdev->tx_channel);
if (tdev->rx_channel && tdev->rx_channel != tdev->tx_channel)
mbox_free_channel(tdev->rx_channel);
return ret;
}
static void mbox_test_remove(struct platform_device *pdev)
@@ -426,7 +438,7 @@ static void mbox_test_remove(struct platform_device *pdev)
if (tdev->tx_channel)
mbox_free_channel(tdev->tx_channel);
if (tdev->rx_channel)
if (tdev->rx_channel && tdev->rx_channel != tdev->tx_channel)
mbox_free_channel(tdev->rx_channel);
}

View File

@@ -18,8 +18,6 @@
#include <linux/property.h>
#include <linux/spinlock.h>
#include "mailbox.h"
static LIST_HEAD(mbox_cons);
static DEFINE_MUTEX(con_mutex);
@@ -52,7 +50,7 @@ static void msg_submit(struct mbox_chan *chan)
int err = -EBUSY;
scoped_guard(spinlock_irqsave, &chan->lock) {
if (!chan->msg_count || chan->active_req)
if (!chan->msg_count || chan->active_req != MBOX_NO_MSG)
break;
count = chan->msg_count;
@@ -74,7 +72,7 @@ static void msg_submit(struct mbox_chan *chan)
}
}
if (!err && (chan->txdone_method & TXDONE_BY_POLL)) {
if (!err && (chan->txdone_method & MBOX_TXDONE_BY_POLL)) {
/* kick start the timer immediately to avoid delays */
scoped_guard(spinlock_irqsave, &chan->mbox->poll_hrt_lock)
hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
@@ -87,13 +85,13 @@ static void tx_tick(struct mbox_chan *chan, int r)
scoped_guard(spinlock_irqsave, &chan->lock) {
mssg = chan->active_req;
chan->active_req = NULL;
chan->active_req = MBOX_NO_MSG;
}
/* Submit next message */
msg_submit(chan);
if (!mssg)
if (mssg == MBOX_NO_MSG)
return;
/* Notify the client */
@@ -114,7 +112,7 @@ static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer)
for (i = 0; i < mbox->num_chans; i++) {
struct mbox_chan *chan = &mbox->chans[i];
if (chan->active_req && chan->cl) {
if (chan->active_req != MBOX_NO_MSG && chan->cl) {
txdone = chan->mbox->ops->last_tx_done(chan);
if (txdone)
tx_tick(chan, 0);
@@ -164,7 +162,7 @@ EXPORT_SYMBOL_GPL(mbox_chan_received_data);
*/
void mbox_chan_txdone(struct mbox_chan *chan, int r)
{
if (unlikely(!(chan->txdone_method & TXDONE_BY_IRQ))) {
if (unlikely(!(chan->txdone_method & MBOX_TXDONE_BY_IRQ))) {
dev_err(chan->mbox->dev,
"Controller can't run the TX ticker\n");
return;
@@ -185,7 +183,7 @@ EXPORT_SYMBOL_GPL(mbox_chan_txdone);
*/
void mbox_client_txdone(struct mbox_chan *chan, int r)
{
if (unlikely(!(chan->txdone_method & TXDONE_BY_ACK))) {
if (unlikely(!(chan->txdone_method & MBOX_TXDONE_BY_ACK))) {
dev_err(chan->mbox->dev, "Client can't run the TX ticker\n");
return;
}
@@ -218,6 +216,29 @@ bool mbox_client_peek_data(struct mbox_chan *chan)
}
EXPORT_SYMBOL_GPL(mbox_client_peek_data);
/**
* mbox_chan_tx_slots_available - Query the number of available TX queue slots.
* @chan: Mailbox channel to query.
*
* Clients may call this to check how many messages can be queued via
* mbox_send_message() before the channel's TX queue is full. This helps
* clients avoid the -ENOBUFS error without needing to increase
* MBOX_TX_QUEUE_LEN.
* This can be called from atomic context.
*
* Return: Number of available slots in the channel's TX queue.
*/
unsigned int mbox_chan_tx_slots_available(struct mbox_chan *chan)
{
unsigned int ret;
guard(spinlock_irqsave)(&chan->lock);
ret = MBOX_TX_QUEUE_LEN - chan->msg_count;
return ret;
}
EXPORT_SYMBOL_GPL(mbox_chan_tx_slots_available);
/**
* mbox_send_message - For client to submit a message to be
* sent to the remote.
@@ -246,7 +267,7 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
{
int t;
if (!chan || !chan->cl)
if (!chan || !chan->cl || mssg == MBOX_NO_MSG)
return -EINVAL;
t = add_to_rbuf(chan, mssg);
@@ -319,12 +340,12 @@ static int __mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl)
scoped_guard(spinlock_irqsave, &chan->lock) {
chan->msg_free = 0;
chan->msg_count = 0;
chan->active_req = NULL;
chan->active_req = MBOX_NO_MSG;
chan->cl = cl;
init_completion(&chan->tx_complete);
if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
chan->txdone_method = TXDONE_BY_ACK;
if (chan->txdone_method == MBOX_TXDONE_BY_POLL && cl->knows_txdone)
chan->txdone_method = MBOX_TXDONE_BY_ACK;
}
if (chan->mbox->ops->startup) {
@@ -341,7 +362,7 @@ static int __mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl)
}
/**
* mbox_bind_client - Request a mailbox channel.
* mbox_bind_client - Bind client to a mailbox channel.
* @chan: The mailbox channel to bind the client to.
* @cl: Identity of the client requesting the channel.
*
@@ -477,9 +498,9 @@ void mbox_free_channel(struct mbox_chan *chan)
/* The queued TX requests are simply aborted, no callbacks are made */
scoped_guard(spinlock_irqsave, &chan->lock) {
chan->cl = NULL;
chan->active_req = NULL;
if (chan->txdone_method == TXDONE_BY_ACK)
chan->txdone_method = TXDONE_BY_POLL;
chan->active_req = MBOX_NO_MSG;
if (chan->txdone_method == MBOX_TXDONE_BY_ACK)
chan->txdone_method = MBOX_TXDONE_BY_POLL;
}
module_put(chan->mbox->dev->driver->owner);
@@ -505,18 +526,17 @@ int mbox_controller_register(struct mbox_controller *mbox)
{
int i, txdone;
/* Sanity check */
if (!mbox || !mbox->dev || !mbox->ops || !mbox->num_chans)
if (!mbox || !mbox->dev || !mbox->ops || !mbox->chans || !mbox->num_chans)
return -EINVAL;
if (mbox->txdone_irq)
txdone = TXDONE_BY_IRQ;
txdone = MBOX_TXDONE_BY_IRQ;
else if (mbox->txdone_poll)
txdone = TXDONE_BY_POLL;
txdone = MBOX_TXDONE_BY_POLL;
else /* It has to be ACK then */
txdone = TXDONE_BY_ACK;
txdone = MBOX_TXDONE_BY_ACK;
if (txdone == TXDONE_BY_POLL) {
if (txdone == MBOX_TXDONE_BY_POLL) {
if (!mbox->ops->last_tx_done) {
dev_err(mbox->dev, "last_tx_done method is absent\n");
@@ -532,6 +552,7 @@ int mbox_controller_register(struct mbox_controller *mbox)
chan->cl = NULL;
chan->mbox = mbox;
chan->active_req = MBOX_NO_MSG;
chan->txdone_method = txdone;
spin_lock_init(&chan->lock);
}

View File

@@ -1,12 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __MAILBOX_H
#define __MAILBOX_H
#include <linux/bits.h>
#define TXDONE_BY_IRQ BIT(0) /* controller has remote RTR irq */
#define TXDONE_BY_POLL BIT(1) /* controller can read status of last TX */
#define TXDONE_BY_ACK BIT(2) /* S/W ACK received by Client ticks the TX */
#endif /* __MAILBOX_H */

View File

@@ -493,14 +493,14 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
if (curr_pa == end_pa - CMDQ_INST_SIZE ||
curr_pa == end_pa) {
/* set to this task directly */
writel(task->pa_base >> cmdq->pdata->shift,
thread->base + CMDQ_THR_CURR_ADDR);
gce_addr = cmdq_convert_gce_addr(task->pa_base, cmdq->pdata);
writel(gce_addr, thread->base + CMDQ_THR_CURR_ADDR);
} else {
cmdq_task_insert_into_thread(task);
smp_mb(); /* modify jump before enable thread */
}
writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->pdata->shift,
thread->base + CMDQ_THR_END_ADDR);
gce_addr = cmdq_convert_gce_addr(task->pa_base + pkt->cmd_buf_size, cmdq->pdata);
writel(gce_addr, thread->base + CMDQ_THR_END_ADDR);
cmdq_thread_resume(thread);
}
list_move_tail(&task->list_entry, &thread->task_busy_list);
@@ -728,7 +728,7 @@ static int cmdq_probe(struct platform_device *pdev)
cmdq->mbox.ops = &cmdq_mbox_chan_ops;
cmdq->mbox.of_xlate = cmdq_xlate;
/* make use of TXDONE_BY_ACK */
/* make use of MBOX_TXDONE_BY_ACK */
cmdq->mbox.txdone_irq = false;
cmdq->mbox.txdone_poll = false;

View File

@@ -50,7 +50,7 @@ static struct mbox_chan *mtk_vcp_mbox_xlate(struct mbox_controller *mbox,
const struct of_phandle_args *sp)
{
if (sp->args_count)
return NULL;
return ERR_PTR(-EINVAL);
return &mbox->chans[0];
}

View File

@@ -22,8 +22,6 @@
#include <linux/pm_runtime.h>
#include <linux/mailbox_controller.h>
#include "mailbox.h"
#define MAILBOX_REVISION 0x000
#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
#define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m))
@@ -240,7 +238,7 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
}
if (mbox->send_no_irq)
mbox->chan->txdone_method = TXDONE_BY_ACK;
mbox->chan->txdone_method = MBOX_TXDONE_BY_ACK;
omap_mbox_enable_irq(mbox, IRQ_RX);

View File

@@ -59,8 +59,6 @@
#include <linux/io-64-nonatomic-lo-hi.h>
#include <acpi/pcc.h>
#include "mailbox.h"
#define MBOX_IRQ_NAME "pcc-mbox"
/**

View File

@@ -46,7 +46,7 @@ struct rockchip_mbox {
/* The maximum size of buf for each channel */
u32 buf_size;
struct rockchip_mbox_chan *chans;
struct rockchip_mbox_chan chans[];
};
static int rockchip_mbox_send_data(struct mbox_chan *chan, void *data)
@@ -173,15 +173,10 @@ static int rockchip_mbox_probe(struct platform_device *pdev)
drv_data = (const struct rockchip_mbox_data *) device_get_match_data(&pdev->dev);
mb = devm_kzalloc(&pdev->dev, sizeof(*mb), GFP_KERNEL);
mb = devm_kzalloc(&pdev->dev, struct_size(mb, chans, drv_data->num_chans), GFP_KERNEL);
if (!mb)
return -ENOMEM;
mb->chans = devm_kcalloc(&pdev->dev, drv_data->num_chans,
sizeof(*mb->chans), GFP_KERNEL);
if (!mb->chans)
return -ENOMEM;
mb->mbox.chans = devm_kcalloc(&pdev->dev, drv_data->num_chans,
sizeof(*mb->mbox.chans), GFP_KERNEL);
if (!mb->mbox.chans)

View File

@@ -16,8 +16,6 @@
#include <dt-bindings/mailbox/tegra186-hsp.h>
#include "mailbox.h"
#define HSP_INT_IE(x) (0x100 + ((x) * 4))
#define HSP_INT_IV 0x300
#define HSP_INT_IR 0x304
@@ -497,7 +495,7 @@ static int tegra_hsp_mailbox_flush(struct mbox_chan *chan,
mbox_chan_txdone(chan, 0);
/* Wait until channel is empty */
if (chan->active_req != NULL)
if (chan->active_req != MBOX_NO_MSG)
continue;
return 0;
@@ -516,7 +514,7 @@ static int tegra_hsp_mailbox_startup(struct mbox_chan *chan)
struct tegra_hsp *hsp = mb->channel.hsp;
unsigned long flags;
chan->txdone_method = TXDONE_BY_IRQ;
chan->txdone_method = MBOX_TXDONE_BY_IRQ;
/*
* Shared mailboxes start out as consumers by default. FULL and EMPTY

View File

@@ -45,6 +45,7 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg);
int mbox_flush(struct mbox_chan *chan, unsigned long timeout);
void mbox_client_txdone(struct mbox_chan *chan, int r); /* atomic */
bool mbox_client_peek_data(struct mbox_chan *chan); /* atomic */
unsigned int mbox_chan_tx_slots_available(struct mbox_chan *chan); /* atomic */
void mbox_free_channel(struct mbox_chan *chan); /* may sleep */
#endif /* __MAILBOX_CLIENT_H */

View File

@@ -3,6 +3,7 @@
#ifndef __MAILBOX_CONTROLLER_H
#define __MAILBOX_CONTROLLER_H
#include <linux/bits.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/hrtimer.h>
@@ -11,6 +12,13 @@
struct mbox_chan;
/* Sentinel value distinguishing "no active request" from "NULL message data" */
#define MBOX_NO_MSG ((void *)-1)
#define MBOX_TXDONE_BY_IRQ BIT(0) /* controller has remote RTR irq */
#define MBOX_TXDONE_BY_POLL BIT(1) /* controller can read status of last TX */
#define MBOX_TXDONE_BY_ACK BIT(2) /* S/W ACK received by Client ticks the TX */
/**
* struct mbox_chan_ops - methods to control mailbox channels
* @send_data: The API asks the MBOX controller driver, in atomic
@@ -54,10 +62,10 @@ struct mbox_chan_ops {
/**
* struct mbox_controller - Controller of a class of communication channels
* @dev: Device backing this controller
* @ops: Operators that work on each communication chan
* @chans: Array of channels
* @num_chans: Number of channels in the 'chans' array.
* @dev: Device backing this controller. Required.
* @ops: Operators that work on each communication chan. Required.
* @chans: Array of channels. Required.
* @num_chans: Number of channels in the 'chans' array. Required.
* @txdone_irq: Indicates if the controller can report to API when
* the last transmitted data was read by the remote.
* Eg, if it has some TX ACK irq.
@@ -70,6 +78,7 @@ struct mbox_chan_ops {
* @of_xlate: Controller driver specific mapping of channel via DT
* @poll_hrt: API private. hrtimer used to poll for TXDONE on all
* channels.
* @poll_hrt_lock: API private. Lock protecting access to poll_hrt.
* @node: API private. To hook into list of controllers.
*/
struct mbox_controller {