diff options
| author | Breno Leitao <leitao@debian.org> | 2026-08-05 07:52:36 -0700 |
|---|---|---|
| committer | Tejun Heo <tj@kernel.org> | 2026-08-10 11:47:20 -1000 |
| commit | a5bde5d8fde8a8cb28e59a672d5ddc5b9c1e7656 (patch) | |
| tree | 39f5b258386e1127d253d293194e9a2991bf3c34 /drivers/gpu/ipu-v3/ipu-smfc.c | |
| download | linux-stable-a5bde5d8fde8a8cb28e59a672d5ddc5b9c1e7656.tar.gz linux-stable-a5bde5d8fde8a8cb28e59a672d5ddc5b9c1e7656.zip | |
workqueue: skip the node_nr_active update for non-unbound workqueuesgrafted
apply_wqattrs_commit() updates node_nr_active->max unconditionally.
wq->node_nr_active[] is only allocated for unbound workqueues, so guard
the call before per-cpu workqueues start using this path.
No functional change: only unbound workqueues reach apply_wqattrs_*()
today.
Signed-off-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/gpu/ipu-v3/ipu-smfc.c')
| -rw-r--r-- | drivers/gpu/ipu-v3/ipu-smfc.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/drivers/gpu/ipu-v3/ipu-smfc.c b/drivers/gpu/ipu-v3/ipu-smfc.c new file mode 100644 index 000000000..46ffc0a59 --- /dev/null +++ b/drivers/gpu/ipu-v3/ipu-smfc.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. + */ +#include <linux/export.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/errno.h> +#include <linux/spinlock.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <video/imx-ipu-v3.h> + +#include "ipu-prv.h" + +struct ipu_smfc { + struct ipu_smfc_priv *priv; + int chno; + bool inuse; +}; + +struct ipu_smfc_priv { + void __iomem *base; + spinlock_t lock; + struct ipu_soc *ipu; + struct ipu_smfc channel[4]; + int use_count; +}; + +/*SMFC Registers */ +#define SMFC_MAP 0x0000 +#define SMFC_WMC 0x0004 +#define SMFC_BS 0x0008 + +int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize) +{ + struct ipu_smfc_priv *priv = smfc->priv; + unsigned long flags; + u32 val, shift; + + spin_lock_irqsave(&priv->lock, flags); + + shift = smfc->chno * 4; + val = readl(priv->base + SMFC_BS); + val &= ~(0xf << shift); + val |= burstsize << shift; + writel(val, priv->base + SMFC_BS); + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize); + +int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id) +{ + struct ipu_smfc_priv *priv = smfc->priv; + unsigned long flags; + u32 val, shift; + + spin_lock_irqsave(&priv->lock, flags); + + shift = smfc->chno * 3; + val = readl(priv->base + SMFC_MAP); + val &= ~(0x7 << shift); + val |= ((csi_id << 2) | mipi_id) << shift; + writel(val, priv->base + SMFC_MAP); + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_smfc_map_channel); + +int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level) +{ + struct ipu_smfc_priv *priv = smfc->priv; + unsigned long flags; + u32 val, shift; + + spin_lock_irqsave(&priv->lock, flags); + + shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0); + val = readl(priv->base + SMFC_WMC); + val &= ~(0x3f << shift); + val |= ((clr_level << 3) | set_level) << shift; + writel(val, priv->base + SMFC_WMC); + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark); + +int ipu_smfc_enable(struct ipu_smfc *smfc) +{ + struct ipu_smfc_priv *priv = smfc->priv; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + if (!priv->use_count) + ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN); + + priv->use_count++; + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_smfc_enable); + +int ipu_smfc_disable(struct ipu_smfc *smfc) +{ + struct ipu_smfc_priv *priv = smfc->priv; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + priv->use_count--; + + if (!priv->use_count) + ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN); + + if (priv->use_count < 0) + priv->use_count = 0; + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_smfc_disable); + +struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno) +{ + struct ipu_smfc_priv *priv = ipu->smfc_priv; + struct ipu_smfc *smfc, *ret; + unsigned long flags; + + if (chno >= 4) + return ERR_PTR(-EINVAL); + + smfc = &priv->channel[chno]; + ret = smfc; + + spin_lock_irqsave(&priv->lock, flags); + + if (smfc->inuse) { + ret = ERR_PTR(-EBUSY); + goto unlock; + } + + smfc->inuse = true; +unlock: + spin_unlock_irqrestore(&priv->lock, flags); + return ret; +} +EXPORT_SYMBOL_GPL(ipu_smfc_get); + +void ipu_smfc_put(struct ipu_smfc *smfc) +{ + struct ipu_smfc_priv *priv = smfc->priv; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + smfc->inuse = false; + spin_unlock_irqrestore(&priv->lock, flags); +} +EXPORT_SYMBOL_GPL(ipu_smfc_put); + +int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, + unsigned long base) +{ + struct ipu_smfc_priv *priv; + int i; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + ipu->smfc_priv = priv; + spin_lock_init(&priv->lock); + priv->ipu = ipu; + + priv->base = devm_ioremap(dev, base, PAGE_SIZE); + if (!priv->base) + return -ENOMEM; + + for (i = 0; i < 4; i++) { + priv->channel[i].priv = priv; + priv->channel[i].chno = i; + } + + pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base); + + return 0; +} + +void ipu_smfc_exit(struct ipu_soc *ipu) +{ +} |
