mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 00:51:51 -04:00
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:
@@ -24,6 +24,7 @@ properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,eliza-ipcc
|
||||
- qcom,glymur-ipcc
|
||||
- qcom,kaanapali-ipcc
|
||||
- qcom,milos-ipcc
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user