From dba9a3dfe912dc47c9dbc9ba1f5f65adbf9aea0f Mon Sep 17 00:00:00 2001 From: Arnaud Pouliquen Date: Wed, 22 May 2019 10:25:35 +0200 Subject: mailbox: stm32_ipcc: add spinlock to fix channels concurrent access Add spinlock protection on IPCC register update to avoid race condition. Without this fix, stm32_ipcc_set_bits and stm32_ipcc_clr_bits can be called in parallel for different channels. This results in register corruptions. Signed-off-by: Arnaud Pouliquen Reviewed-by: Fabien Dessenne Signed-off-by: Jassi Brar --- drivers/mailbox/stm32-ipcc.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/stm32-ipcc.c b/drivers/mailbox/stm32-ipcc.c index f91dfb1327c7..5c2d1e1f988b 100644 --- a/drivers/mailbox/stm32-ipcc.c +++ b/drivers/mailbox/stm32-ipcc.c @@ -50,6 +50,7 @@ struct stm32_ipcc { void __iomem *reg_base; void __iomem *reg_proc; struct clk *clk; + spinlock_t lock; /* protect access to IPCC registers */ int irqs[IPCC_IRQ_NUM]; int wkp; u32 proc_id; @@ -58,14 +59,24 @@ struct stm32_ipcc { u32 xmr; }; -static inline void stm32_ipcc_set_bits(void __iomem *reg, u32 mask) +static inline void stm32_ipcc_set_bits(spinlock_t *lock, void __iomem *reg, + u32 mask) { + unsigned long flags; + + spin_lock_irqsave(lock, flags); writel_relaxed(readl_relaxed(reg) | mask, reg); + spin_unlock_irqrestore(lock, flags); } -static inline void stm32_ipcc_clr_bits(void __iomem *reg, u32 mask) +static inline void stm32_ipcc_clr_bits(spinlock_t *lock, void __iomem *reg, + u32 mask) { + unsigned long flags; + + spin_lock_irqsave(lock, flags); writel_relaxed(readl_relaxed(reg) & ~mask, reg); + spin_unlock_irqrestore(lock, flags); } static irqreturn_t stm32_ipcc_rx_irq(int irq, void *data) @@ -92,7 +103,7 @@ static irqreturn_t stm32_ipcc_rx_irq(int irq, void *data) mbox_chan_received_data(&ipcc->controller.chans[chan], NULL); - stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XSCR, + stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XSCR, RX_BIT_CHAN(chan)); ret = IRQ_HANDLED; @@ -121,7 +132,7 @@ static irqreturn_t stm32_ipcc_tx_irq(int irq, void *data) dev_dbg(dev, "%s: chan:%d tx\n", __func__, chan); /* mask 'tx channel free' interrupt */ - stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR, + stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR, TX_BIT_CHAN(chan)); mbox_chan_txdone(&ipcc->controller.chans[chan], 0); @@ -141,10 +152,12 @@ static int stm32_ipcc_send_data(struct mbox_chan *link, void *data) dev_dbg(ipcc->controller.dev, "%s: chan:%d\n", __func__, chan); /* set channel n occupied */ - stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XSCR, TX_BIT_CHAN(chan)); + stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XSCR, + TX_BIT_CHAN(chan)); /* unmask 'tx channel free' interrupt */ - stm32_ipcc_clr_bits(ipcc->reg_proc + IPCC_XMR, TX_BIT_CHAN(chan)); + stm32_ipcc_clr_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR, + TX_BIT_CHAN(chan)); return 0; } @@ -163,7 +176,8 @@ static int stm32_ipcc_startup(struct mbox_chan *link) } /* unmask 'rx channel occupied' interrupt */ - stm32_ipcc_clr_bits(ipcc->reg_proc + IPCC_XMR, RX_BIT_CHAN(chan)); + stm32_ipcc_clr_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR, + RX_BIT_CHAN(chan)); return 0; } @@ -175,7 +189,7 @@ static void stm32_ipcc_shutdown(struct mbox_chan *link) controller); /* mask rx/tx interrupt */ - stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR, + stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR, RX_BIT_CHAN(chan) | TX_BIT_CHAN(chan)); clk_disable_unprepare(ipcc->clk); @@ -208,6 +222,8 @@ static int stm32_ipcc_probe(struct platform_device *pdev) if (!ipcc) return -ENOMEM; + spin_lock_init(&ipcc->lock); + /* proc_id */ if (of_property_read_u32(np, "st,proc-id", &ipcc->proc_id)) { dev_err(dev, "Missing st,proc-id\n"); @@ -259,9 +275,10 @@ static int stm32_ipcc_probe(struct platform_device *pdev) } /* mask and enable rx/tx irq */ - stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR, + stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR, RX_BIT_MASK | TX_BIT_MASK); - stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XCR, XCR_RXOIE | XCR_TXOIE); + stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XCR, + XCR_RXOIE | XCR_TXOIE); /* wakeup */ if (of_property_read_bool(np, "wakeup-source")) { -- cgit v1.2.3 From 06c182c3bc4eebd6038999a611e4c963d4c87a93 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 31 May 2019 15:33:16 +0100 Subject: mailbox: arm_mhu: reorder header inclusion and drop unneeded ones This patch just re-orders some of the headers includes and also drop the ones that are unnecessary. Signed-off-by: Sudeep Holla Signed-off-by: Jassi Brar --- drivers/mailbox/arm_mhu.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/arm_mhu.c b/drivers/mailbox/arm_mhu.c index b47851856086..9da236552bd7 100644 --- a/drivers/mailbox/arm_mhu.c +++ b/drivers/mailbox/arm_mhu.c @@ -5,16 +5,13 @@ * Author: Jassi Brar */ -#include -#include -#include -#include -#include +#include +#include #include +#include #include -#include -#include #include +#include #define INTR_STAT_OFS 0x0 #define INTR_SET_OFS 0x8 -- cgit v1.2.3 From 9c1f2a5dc2948b9f1170d4202c84745f0b0ff0c9 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Tue, 4 Jun 2019 12:01:46 -0500 Subject: mailbox: omap: Add support for TI K3 SoCs The TI K3 AM65x and J721E family of SoCs have a new Mailbox IP that is based on the existing Mailbox IP present in OMAP architecture based SoCs. Each instance of the legacy OMAP Mailbox IP is now a single cluster within the newer Mailbox IP instance on K3 architecture based SoCs. A single K3 Mailbox IP instance has multiple clusters with each cluster providing the same functionality as the existing OMAP Mailbox IP. Reuse the existing OMAP Mailbox driver to extend the support for this newer IP present within the Main NavSS block on K3 SoCs. The K3 family of SoCs use 64-bit ARMv8 processors for running Linux, so the driver is also enhanced to deal with the differences between the 32-bit message payloads and the 64-bit pointers used by the client drivers. Signed-off-by: Suman Anna Signed-off-by: Jassi Brar --- drivers/mailbox/Kconfig | 2 +- drivers/mailbox/omap-mailbox.c | 43 +++++++++++++++++++++++++----------------- include/linux/omap-mailbox.h | 4 +++- 3 files changed, 30 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index b709481a8de6..ab4eb750bbdd 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -54,7 +54,7 @@ config ARMADA_37XX_RWTM_MBOX config OMAP2PLUS_MBOX tristate "OMAP2+ Mailbox framework support" - depends on ARCH_OMAP2PLUS + depends on ARCH_OMAP2PLUS || ARCH_K3 help Mailbox implementation for OMAP family chips with hardware for interprocessor communication involving DSP, IVA1.0 and IVA2 in diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c index ca50177a33f2..a3cd63583cf7 100644 --- a/drivers/mailbox/omap-mailbox.c +++ b/drivers/mailbox/omap-mailbox.c @@ -3,7 +3,7 @@ * OMAP mailbox driver * * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved. - * Copyright (C) 2013-2016 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2013-2019 Texas Instruments Incorporated - http://www.ti.com * * Contact: Hiroshi DOYU * Suman Anna @@ -141,14 +141,14 @@ void mbox_write_reg(struct omap_mbox_device *mdev, u32 val, size_t ofs) } /* Mailbox FIFO handle functions */ -static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) +static u32 mbox_fifo_read(struct omap_mbox *mbox) { struct omap_mbox_fifo *fifo = &mbox->rx_fifo; - return (mbox_msg_t)mbox_read_reg(mbox->parent, fifo->msg); + return mbox_read_reg(mbox->parent, fifo->msg); } -static void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) +static void mbox_fifo_write(struct omap_mbox *mbox, u32 msg) { struct omap_mbox_fifo *fifo = &mbox->tx_fifo; @@ -256,14 +256,16 @@ static void mbox_rx_work(struct work_struct *work) { struct omap_mbox_queue *mq = container_of(work, struct omap_mbox_queue, work); - mbox_msg_t msg; + mbox_msg_t data; + u32 msg; int len; while (kfifo_len(&mq->fifo) >= sizeof(msg)) { len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); WARN_ON(len != sizeof(msg)); + data = msg; - mbox_chan_received_data(mq->mbox->chan, (void *)msg); + mbox_chan_received_data(mq->mbox->chan, (void *)data); spin_lock_irq(&mq->lock); if (mq->full) { mq->full = false; @@ -286,7 +288,7 @@ static void __mbox_tx_interrupt(struct omap_mbox *mbox) static void __mbox_rx_interrupt(struct omap_mbox *mbox) { struct omap_mbox_queue *mq = mbox->rxq; - mbox_msg_t msg; + u32 msg; int len; while (!mbox_fifo_empty(mbox)) { @@ -540,13 +542,13 @@ static void omap_mbox_chan_shutdown(struct mbox_chan *chan) mutex_unlock(&mdev->cfg_lock); } -static int omap_mbox_chan_send_noirq(struct omap_mbox *mbox, void *data) +static int omap_mbox_chan_send_noirq(struct omap_mbox *mbox, u32 msg) { int ret = -EBUSY; if (!mbox_fifo_full(mbox)) { _omap_mbox_enable_irq(mbox, IRQ_RX); - mbox_fifo_write(mbox, (mbox_msg_t)data); + mbox_fifo_write(mbox, msg); ret = 0; _omap_mbox_disable_irq(mbox, IRQ_RX); @@ -558,12 +560,12 @@ static int omap_mbox_chan_send_noirq(struct omap_mbox *mbox, void *data) return ret; } -static int omap_mbox_chan_send(struct omap_mbox *mbox, void *data) +static int omap_mbox_chan_send(struct omap_mbox *mbox, u32 msg) { int ret = -EBUSY; if (!mbox_fifo_full(mbox)) { - mbox_fifo_write(mbox, (mbox_msg_t)data); + mbox_fifo_write(mbox, msg); ret = 0; } @@ -576,14 +578,15 @@ static int omap_mbox_chan_send_data(struct mbox_chan *chan, void *data) { struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan); int ret; + u32 msg = omap_mbox_message(data); if (!mbox) return -EINVAL; if (mbox->send_no_irq) - ret = omap_mbox_chan_send_noirq(mbox, data); + ret = omap_mbox_chan_send_noirq(mbox, msg); else - ret = omap_mbox_chan_send(mbox, data); + ret = omap_mbox_chan_send(mbox, msg); return ret; } @@ -656,6 +659,10 @@ static const struct of_device_id omap_mailbox_of_match[] = { .compatible = "ti,omap4-mailbox", .data = &omap4_data, }, + { + .compatible = "ti,am654-mailbox", + .data = &omap4_data, + }, { /* end */ }, @@ -830,7 +837,10 @@ static int omap_mbox_probe(struct platform_device *pdev) mdev->intr_type = intr_type; mdev->mboxes = list; - /* OMAP does not have a Tx-Done IRQ, but rather a Tx-Ready IRQ */ + /* + * OMAP/K3 Mailbox IP does not have a Tx-Done IRQ, but rather a Tx-Ready + * IRQ and is needed to run the Tx state machine + */ mdev->controller.txdone_irq = true; mdev->controller.dev = mdev->dev; mdev->controller.ops = &omap_mbox_chan_ops; @@ -899,9 +909,8 @@ static int __init omap_mbox_init(void) return err; /* kfifo size sanity check: alignment and minimal size */ - mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t)); - mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, - sizeof(mbox_msg_t)); + mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(u32)); + mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, sizeof(u32)); err = platform_driver_register(&omap_mbox_driver); if (err) diff --git a/include/linux/omap-mailbox.h b/include/linux/omap-mailbox.h index 6dbcd2da0332..8aa984ec1f38 100644 --- a/include/linux/omap-mailbox.h +++ b/include/linux/omap-mailbox.h @@ -6,7 +6,9 @@ #ifndef OMAP_MAILBOX_H #define OMAP_MAILBOX_H -typedef u32 mbox_msg_t; +typedef uintptr_t mbox_msg_t; + +#define omap_mbox_message(data) (u32)(mbox_msg_t)(data) typedef int __bitwise omap_mbox_irq_t; #define IRQ_TX ((__force omap_mbox_irq_t) 1) -- cgit v1.2.3 From 11108f4671bda6bf93bea5455210346a0ccbaa10 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 27 Jun 2019 15:29:27 +0300 Subject: mailbox: imx: Clear GIEn bit at shutdown GIEn is enabled at startup for RX doorbell mailboxes so we need to clear the bit at shutdown in order to avoid leaving the interrupt line enabled. Signed-off-by: Daniel Baluta Reviewed-by: Oleksij Rempel Signed-off-by: Jassi Brar --- drivers/mailbox/imx-mailbox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c index 25be8bb5e371..9f74dee1a58c 100644 --- a/drivers/mailbox/imx-mailbox.c +++ b/drivers/mailbox/imx-mailbox.c @@ -217,8 +217,8 @@ static void imx_mu_shutdown(struct mbox_chan *chan) if (cp->type == IMX_MU_TYPE_TXDB) tasklet_kill(&cp->txdb_tasklet); - imx_mu_xcr_rmw(priv, 0, - IMX_MU_xCR_TIEn(cp->idx) | IMX_MU_xCR_RIEn(cp->idx)); + imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_TIEn(cp->idx) | + IMX_MU_xCR_RIEn(cp->idx) | IMX_MU_xCR_GIEn(cp->idx)); free_irq(priv->irq, chan); } -- cgit v1.2.3 From 7836922d87175dbc9bc972a1aca08d2c8b6f5045 Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Thu, 4 Jul 2019 10:36:27 +0800 Subject: mailbox: bcm-flexrm-mailbox: using dev_get_drvdata directly Several drivers cast a struct device pointer to a struct platform_device pointer only to then call platform_get_drvdata(). To improve readability, these constructs can be simplified by using dev_get_drvdata() directly. Signed-off-by: Fuqian Huang Signed-off-by: Jassi Brar --- drivers/mailbox/bcm-flexrm-mailbox.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/bcm-flexrm-mailbox.c b/drivers/mailbox/bcm-flexrm-mailbox.c index a64116586b4c..0cfdd53d04a1 100644 --- a/drivers/mailbox/bcm-flexrm-mailbox.c +++ b/drivers/mailbox/bcm-flexrm-mailbox.c @@ -1165,8 +1165,7 @@ static int flexrm_process_completions(struct flexrm_ring *ring) static int flexrm_debugfs_conf_show(struct seq_file *file, void *offset) { - struct platform_device *pdev = to_platform_device(file->private); - struct flexrm_mbox *mbox = platform_get_drvdata(pdev); + struct flexrm_mbox *mbox = dev_get_drvdata(file->private); /* Write config in file */ flexrm_write_config_in_seqfile(mbox, file); @@ -1176,8 +1175,7 @@ static int flexrm_debugfs_conf_show(struct seq_file *file, void *offset) static int flexrm_debugfs_stats_show(struct seq_file *file, void *offset) { - struct platform_device *pdev = to_platform_device(file->private); - struct flexrm_mbox *mbox = platform_get_drvdata(pdev); + struct flexrm_mbox *mbox = dev_get_drvdata(file->private); /* Write stats in file */ flexrm_write_stats_in_seqfile(mbox, file); -- cgit v1.2.3 From b1a399530ca9bc958ac48fe85837c791f89a3be2 Mon Sep 17 00:00:00 2001 From: Bitan Biswas Date: Fri, 14 Jun 2019 09:31:00 -0700 Subject: mailbox: tegra: hsp: add noirq resume Add noirq resume instead of resume callback for Tegra HSP. Tegra HSP resume needs tegra_hsp_doorbell_startup() call to fix timeout error for tegra_bpmp_transfer() during genpd resume noirq on Jetson TX2. Signed-off-by: Bitan Biswas Signed-off-by: Jassi Brar --- drivers/mailbox/tegra-hsp.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c index 91f1a0c62779..91e223e05e1d 100644 --- a/drivers/mailbox/tegra-hsp.c +++ b/drivers/mailbox/tegra-hsp.c @@ -775,6 +775,12 @@ static int __maybe_unused tegra_hsp_resume(struct device *dev) { struct tegra_hsp *hsp = dev_get_drvdata(dev); unsigned int i; + struct tegra_hsp_doorbell *db; + + list_for_each_entry(db, &hsp->doorbells, list) { + if (db && db->channel.chan) + tegra_hsp_doorbell_startup(db->channel.chan); + } for (i = 0; i < hsp->num_sm; i++) { struct tegra_hsp_mailbox *mb = &hsp->mailboxes[i]; @@ -786,7 +792,9 @@ static int __maybe_unused tegra_hsp_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(tegra_hsp_pm_ops, NULL, tegra_hsp_resume); +static const struct dev_pm_ops tegra_hsp_pm_ops = { + .resume_noirq = tegra_hsp_resume, +}; static const struct tegra_hsp_db_map tegra186_hsp_db_map[] = { { "ccplex", TEGRA_HSP_DB_MASTER_CCPLEX, HSP_DB_CCPLEX, }, -- cgit v1.2.3 From 20b5d24c7669813ec73589146f7dcefbf259a26a Mon Sep 17 00:00:00 2001 From: Bitan Biswas Date: Fri, 14 Jun 2019 09:31:01 -0700 Subject: mailbox: tegra: avoid resume NULL mailboxes If Tegra HSP device tree does not have 'shared irqs', mailboxes pointer is NULL. Add non-NULL HSP mailboxes check in resume callback before tegra_hsp_mailbox_startup() call and prevent NULL pointer exception. Signed-off-by: Bitan Biswas Signed-off-by: Jassi Brar --- drivers/mailbox/tegra-hsp.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c index 91e223e05e1d..4c5ba35d48d4 100644 --- a/drivers/mailbox/tegra-hsp.c +++ b/drivers/mailbox/tegra-hsp.c @@ -782,11 +782,13 @@ static int __maybe_unused tegra_hsp_resume(struct device *dev) tegra_hsp_doorbell_startup(db->channel.chan); } - for (i = 0; i < hsp->num_sm; i++) { - struct tegra_hsp_mailbox *mb = &hsp->mailboxes[i]; + if (hsp->mailboxes) { + for (i = 0; i < hsp->num_sm; i++) { + struct tegra_hsp_mailbox *mb = &hsp->mailboxes[i]; - if (mb->channel.chan->cl) - tegra_hsp_mailbox_startup(mb->channel.chan); + if (mb->channel.chan->cl) + tegra_hsp_mailbox_startup(mb->channel.chan); + } } return 0; -- cgit v1.2.3 From 25777e5784a7b417967460d4fcf9660d05a0c320 Mon Sep 17 00:00:00 2001 From: morten petersen Date: Mon, 8 Jul 2019 11:41:54 +0000 Subject: mailbox: handle failed named mailbox channel request Previously, if mbox_request_channel_byname was used with a name which did not exist in the "mbox-names" property of a mailbox client, the mailbox corresponding to the last entry in the "mbox-names" list would be incorrectly selected. With this patch, -EINVAL is returned if the named mailbox is not found. Signed-off-by: Morten Borup Petersen Signed-off-by: Jassi Brar --- drivers/mailbox/mailbox.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c index f4b1950d35f3..0b821a5b2db8 100644 --- a/drivers/mailbox/mailbox.c +++ b/drivers/mailbox/mailbox.c @@ -418,11 +418,13 @@ struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl, of_property_for_each_string(np, "mbox-names", prop, mbox_name) { if (!strncmp(name, mbox_name, strlen(name))) - break; + return mbox_request_channel(cl, index); index++; } - return mbox_request_channel(cl, index); + dev_err(cl->dev, "%s() could not locate channel named \"%s\"\n", + __func__, name); + return ERR_PTR(-EINVAL); } EXPORT_SYMBOL_GPL(mbox_request_channel_byname); -- cgit v1.2.3