diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-02 10:54:11 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-02 10:54:11 -0700 |
| commit | ba3e43a9e601636f5edb54e259a74f96ca3b8fd8 (patch) | |
| tree | ce29ed8b5df5557a7f2b2e1d4ca9f6126b980f76 /drivers/soc | |
| parent | 4a694a77c3d60bc974c6ef7fb98cdb872b5330ea (diff) | |
| parent | fce4668a01227abb2c60e3202cf866137fbfcef2 (diff) | |
Pull SoC fixes from Arnd Bergmann:
"Following the previous set of fixes, this addresses another
significant number of small issues found in firmware drivers (tee,
optee, qcomtee, qcom ice, exynos acpm) drivers through various tools.
This is about error handling, resource leaks, concurrency and a
use-after-free bug.
The fixes for the Qualcomm ICE driver also introduce interface changes
in the UFS and MMC drivers using it.
Outside of firmware drivers, there are a few fixes across the tree:
- Minor driver code mistakes in the Atmel EBI memory controller, the
i.MX soc ID driver and socfpga boot logic
- A defconfig change to avoid a boot time regression on multiple
qualcomm boards
- Device tree fixes for qualcomm, at91 and gemini, addressing mostly
minor configuration mistakes"
* tag 'soc-fixes-7.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (28 commits)
firmware: samsung: acpm: Fix infinite loop on sequence number exhaustion
firmware: samsung: acpm: Fix missing LKMM barriers in sequence allocator
firmware: samsung: acpm: Fix false timeouts and Use-After-Free in polling
ARM: dts: gemini: Fix partition offsets
ARM: socfpga: Fix OF node refcount leak in SMP setup
soc: qcom: ice: Fix the error code when 'qcom,ice' property is not found
arm64: dts: qcom: eliza: Add power-domain and iface clk for ice node
arm64: dts: qcom: milos: Add power-domain and iface clk for ice node
tee: qcomtee: add missing va_end in early return qcomtee_object_user_init()
tee: fix params_from_user() error path in tee_ioctl_supp_recv
tee: shm: fix shm leak in register_shm_helper()
tee: fix tee_ioctl_object_invoke_arg padding
arm64: defconfig: Enable PCI M.2 power sequencing driver
scsi: ufs: ufs-qcom: Remove NULL check from devm_of_qcom_ice_get()
mmc: sdhci-msm: Remove NULL check from devm_of_qcom_ice_get()
soc: qcom: ice: Return proper error codes from devm_of_qcom_ice_get() instead of NULL
soc: qcom: ice: Return -ENODEV if the ICE platform device is not found
soc: qcom: ice: Fix race between qcom_ice_probe() and of_qcom_ice_get()
ARM: dts: microchip: sam9x7: fix GMAC clock configuration
firmware: samsung: acpm: Fix mailbox channel leak on probe error
...
Diffstat (limited to 'drivers/soc')
| -rw-r--r-- | drivers/soc/imx/soc-imx8m.c | 2 | ||||
| -rw-r--r-- | drivers/soc/qcom/ice.c | 66 |
2 files changed, 52 insertions, 16 deletions
diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c index 77763a107edb..fc080e56f50d 100644 --- a/drivers/soc/imx/soc-imx8m.c +++ b/drivers/soc/imx/soc-imx8m.c @@ -247,7 +247,7 @@ static int imx8m_soc_probe(struct platform_device *pdev) if (ret) return ret; - data = device_get_match_data(dev); + data = of_machine_get_match_data(imx8_soc_match); if (data) { soc_dev_attr->soc_id = data->name; ret = imx8m_soc_prepare(pdev, data->ocotp_compatible); diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c index b203bc685cad..5f20108aa03e 100644 --- a/drivers/soc/qcom/ice.c +++ b/drivers/soc/qcom/ice.c @@ -16,6 +16,7 @@ #include <linux/of.h> #include <linux/of_platform.h> #include <linux/platform_device.h> +#include <linux/xarray.h> #include <linux/firmware/qcom/qcom_scm.h> @@ -108,11 +109,15 @@ struct qcom_ice { void __iomem *base; struct clk *core_clk; + struct clk *iface_clk; bool use_hwkm; bool hwkm_init_complete; u8 hwkm_version; }; +static DEFINE_XARRAY(ice_handles); +static DEFINE_MUTEX(ice_mutex); + static bool qcom_ice_check_supported(struct qcom_ice *ice) { u32 regval = qcom_ice_readl(ice, QCOM_ICE_REG_VERSION); @@ -312,8 +317,13 @@ int qcom_ice_resume(struct qcom_ice *ice) err = clk_prepare_enable(ice->core_clk); if (err) { - dev_err(dev, "failed to enable core clock (%d)\n", - err); + dev_err(dev, "Failed to enable core clock: %d\n", err); + return err; + } + + err = clk_prepare_enable(ice->iface_clk); + if (err) { + dev_err(dev, "Failed to enable iface clock: %d\n", err); return err; } qcom_ice_hwkm_init(ice); @@ -323,6 +333,7 @@ EXPORT_SYMBOL_GPL(qcom_ice_resume); int qcom_ice_suspend(struct qcom_ice *ice) { + clk_disable_unprepare(ice->iface_clk); clk_disable_unprepare(ice->core_clk); ice->hwkm_init_complete = false; @@ -559,7 +570,7 @@ static struct qcom_ice *qcom_ice_create(struct device *dev, if (!qcom_scm_ice_available()) { dev_warn(dev, "ICE SCM interface not found\n"); - return NULL; + return ERR_PTR(-EOPNOTSUPP); } engine = devm_kzalloc(dev, sizeof(*engine), GFP_KERNEL); @@ -580,10 +591,16 @@ static struct qcom_ice *qcom_ice_create(struct device *dev, if (!engine->core_clk) engine->core_clk = devm_clk_get_optional_enabled(dev, "ice"); if (!engine->core_clk) + engine->core_clk = devm_clk_get_optional_enabled(dev, "core"); + if (!engine->core_clk) engine->core_clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(engine->core_clk)) return ERR_CAST(engine->core_clk); + engine->iface_clk = devm_clk_get_optional_enabled(dev, "iface"); + if (IS_ERR(engine->iface_clk)) + return ERR_CAST(engine->iface_clk); + if (!qcom_ice_check_supported(engine)) return ERR_PTR(-EOPNOTSUPP); @@ -631,6 +648,8 @@ static struct qcom_ice *of_qcom_ice_get(struct device *dev) return qcom_ice_create(&pdev->dev, base); } + guard(mutex)(&ice_mutex); + /* * If the consumer node does not provider an 'ice' reg range * (legacy DT binding), then it must at least provide a phandle @@ -639,20 +658,21 @@ static struct qcom_ice *of_qcom_ice_get(struct device *dev) struct device_node *node __free(device_node) = of_parse_phandle(dev->of_node, "qcom,ice", 0); if (!node) - return NULL; + return ERR_PTR(-EOPNOTSUPP); pdev = of_find_device_by_node(node); if (!pdev) { dev_err(dev, "Cannot find device node %s\n", node->name); - return ERR_PTR(-EPROBE_DEFER); + return ERR_PTR(-ENODEV); } - ice = platform_get_drvdata(pdev); - if (!ice) { - dev_err(dev, "Cannot get ice instance from %s\n", - dev_name(&pdev->dev)); + ice = xa_load(&ice_handles, pdev->dev.of_node->phandle); + if (IS_ERR_OR_NULL(ice)) { platform_device_put(pdev); - return ERR_PTR(-EPROBE_DEFER); + if (!ice) + return ERR_PTR(-EPROBE_DEFER); + else + return ice; } link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER); @@ -691,8 +711,7 @@ static void devm_of_qcom_ice_put(struct device *dev, void *res) * phandle via 'qcom,ice' property to an ICE DT, the ICE instance will already * be created and so this function will return that instead. * - * Return: ICE pointer on success, NULL if there is no ICE data provided by the - * consumer or ERR_PTR() on error. + * Return: ICE pointer on success, ERR_PTR() on error. */ struct qcom_ice *devm_of_qcom_ice_get(struct device *dev) { @@ -703,7 +722,7 @@ struct qcom_ice *devm_of_qcom_ice_get(struct device *dev) return ERR_PTR(-ENOMEM); ice = of_qcom_ice_get(dev); - if (!IS_ERR_OR_NULL(ice)) { + if (!IS_ERR(ice)) { *dr = ice; devres_add(dev, dr); } else { @@ -716,24 +735,40 @@ EXPORT_SYMBOL_GPL(devm_of_qcom_ice_get); static int qcom_ice_probe(struct platform_device *pdev) { + unsigned long phandle = pdev->dev.of_node->phandle; struct qcom_ice *engine; void __iomem *base; + guard(mutex)(&ice_mutex); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) { dev_warn(&pdev->dev, "ICE registers not found\n"); + /* Store the error pointer for devm_of_qcom_ice_get() */ + xa_store(&ice_handles, phandle, (__force void *)base, GFP_KERNEL); return PTR_ERR(base); } engine = qcom_ice_create(&pdev->dev, base); - if (IS_ERR(engine)) + if (IS_ERR(engine)) { + /* Store the error pointer for devm_of_qcom_ice_get() */ + xa_store(&ice_handles, phandle, engine, GFP_KERNEL); return PTR_ERR(engine); + } - platform_set_drvdata(pdev, engine); + xa_store(&ice_handles, phandle, engine, GFP_KERNEL); return 0; } +static void qcom_ice_remove(struct platform_device *pdev) +{ + unsigned long phandle = pdev->dev.of_node->phandle; + + guard(mutex)(&ice_mutex); + xa_store(&ice_handles, phandle, NULL, GFP_KERNEL); +} + static const struct of_device_id qcom_ice_of_match_table[] = { { .compatible = "qcom,inline-crypto-engine" }, { }, @@ -742,6 +777,7 @@ MODULE_DEVICE_TABLE(of, qcom_ice_of_match_table); static struct platform_driver qcom_ice_driver = { .probe = qcom_ice_probe, + .remove = qcom_ice_remove, .driver = { .name = "qcom-ice", .of_match_table = qcom_ice_of_match_table, |
