diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-25 12:02:16 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-25 12:02:16 -0700 |
commit | a907047732470f75f3b7c9a8ee09b16765b8364c (patch) | |
tree | c14d8b6220f80f4c87e8dc0eb6d6fa2581e9a294 /drivers/soc/microchip/mpfs-sys-controller.c | |
parent | 18032df5ef5c0eec2adf120142bd95a3a8807866 (diff) | |
parent | 4c87f3ff78b20da0dd118762fd66b67a98e36249 (diff) | |
download | linux-a907047732470f75f3b7c9a8ee09b16765b8364c.tar.gz linux-a907047732470f75f3b7c9a8ee09b16765b8364c.tar.bz2 linux-a907047732470f75f3b7c9a8ee09b16765b8364c.zip |
Merge tag 'soc-drivers-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM SoC driver updates from Arnd Bergmann:
"The most notable updates this time are for Qualcomm Snapdragon
platforms. The Inline-Crypto-Engine gets a new DT binding and driver,
and a number of drivers now support additional Snapdragon variants, in
particular the rsc, scm, geni, bwm, glink and socinfo, while the llcc
(edac) and rpm drivers get notable functionality updates.
Updates on other platforms include:
- Various updates to the Mediatek mutex and mmsys drivers, including
support for the Helio X10 SoC
- Support for unidirectional mailbox channels in Arm SCMI firmware
- Support for per cpu asynchronous notification in OP-TEE firmware
- Minor updates for memory controller drivers.
- Minor updates for Renesas, TI, Amlogic, Apple, Broadcom, Tegra,
Allwinner, Versatile Express, Canaan, Microchip, Mediatek and i.MX
SoC drivers, mainly updating the use of MODULE_LICENSE() macros and
obsolete DT driver interfaces"
* tag 'soc-drivers-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (165 commits)
soc: ti: smartreflex: Simplify getting the opam_sr pointer
bus: vexpress-config: Add explicit of_platform.h include
soc: mediatek: Kconfig: Add MTK_CMDQ dependency to MTK_MMSYS
memory: mtk-smi: mt8365: Add SMI Support
dt-bindings: memory-controllers: mediatek,smi-larb: add mt8365
dt-bindings: memory-controllers: mediatek,smi-common: add mt8365
memory: tegra: read values from correct device
dt-bindings: crypto: Add Qualcomm Inline Crypto Engine
soc: qcom: Make the Qualcomm UFS/SDCC ICE a dedicated driver
dt-bindings: firmware: document Qualcomm QCM2290 SCM
soc: qcom: rpmh-rsc: Support RSC v3 minor versions
soc: qcom: smd-rpm: Use GFP_ATOMIC in write path
soc/tegra: fuse: Remove nvmem root only access
soc/tegra: cbb: tegra194: Use of_address_count() helper
soc/tegra: cbb: Remove MODULE_LICENSE in non-modules
ARM: tegra: Remove MODULE_LICENSE in non-modules
soc/tegra: flowctrl: Use devm_platform_get_and_ioremap_resource()
soc: tegra: cbb: Drop empty platform remove function
firmware: arm_scmi: Add support for unidirectional mailbox channels
dt-bindings: firmware: arm,scmi: Support mailboxes unidirectional channels
...
Diffstat (limited to 'drivers/soc/microchip/mpfs-sys-controller.c')
-rw-r--r-- | drivers/soc/microchip/mpfs-sys-controller.c | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/drivers/soc/microchip/mpfs-sys-controller.c b/drivers/soc/microchip/mpfs-sys-controller.c index 6e20207b5756..216d9f4ea0ce 100644 --- a/drivers/soc/microchip/mpfs-sys-controller.c +++ b/drivers/soc/microchip/mpfs-sys-controller.c @@ -11,12 +11,19 @@ #include <linux/slab.h> #include <linux/kref.h> #include <linux/module.h> +#include <linux/jiffies.h> #include <linux/interrupt.h> #include <linux/of_platform.h> #include <linux/mailbox_client.h> #include <linux/platform_device.h> #include <soc/microchip/mpfs.h> +/* + * This timeout must be long, as some services (example: image authentication) + * take significant time to complete + */ +#define MPFS_SYS_CTRL_TIMEOUT_MS 30000 + static DEFINE_MUTEX(transaction_lock); struct mpfs_sys_controller { @@ -28,35 +35,47 @@ struct mpfs_sys_controller { int mpfs_blocking_transaction(struct mpfs_sys_controller *sys_controller, struct mpfs_mss_msg *msg) { - int ret, err; + unsigned long timeout = msecs_to_jiffies(MPFS_SYS_CTRL_TIMEOUT_MS); + int ret; - err = mutex_lock_interruptible(&transaction_lock); - if (err) - return err; + ret = mutex_lock_interruptible(&transaction_lock); + if (ret) + return ret; reinit_completion(&sys_controller->c); ret = mbox_send_message(sys_controller->chan, msg); - if (ret >= 0) { - if (wait_for_completion_timeout(&sys_controller->c, HZ)) { - ret = 0; - } else { - ret = -ETIMEDOUT; - dev_warn(sys_controller->client.dev, - "MPFS sys controller transaction timeout\n"); - } + if (ret < 0) { + dev_warn(sys_controller->client.dev, "MPFS sys controller service timeout\n"); + goto out; + } + + /* + * Unfortunately, the system controller will only deliver an interrupt + * if a service succeeds. mbox_send_message() will block until the busy + * flag is gone. If the busy flag is gone but no interrupt has arrived + * to trigger the rx callback then the service can be deemed to have + * failed. + * The caller can then interrogate msg::response::resp_status to + * determine the cause of the failure. + * mbox_send_message() returns positive integers in the success path, so + * ret needs to be cleared if we do get an interrupt. + */ + if (!wait_for_completion_timeout(&sys_controller->c, timeout)) { + ret = -EBADMSG; + dev_warn(sys_controller->client.dev, "MPFS sys controller service failed\n"); } else { - dev_err(sys_controller->client.dev, - "mpfs sys controller transaction returned %d\n", ret); + ret = 0; } +out: mutex_unlock(&transaction_lock); return ret; } EXPORT_SYMBOL(mpfs_blocking_transaction); -static void rx_callback(struct mbox_client *client, void *msg) +static void mpfs_sys_controller_rx_callback(struct mbox_client *client, void *msg) { struct mpfs_sys_controller *sys_controller = container_of(client, struct mpfs_sys_controller, client); @@ -66,8 +85,8 @@ static void rx_callback(struct mbox_client *client, void *msg) static void mpfs_sys_controller_delete(struct kref *kref) { - struct mpfs_sys_controller *sys_controller = container_of(kref, struct mpfs_sys_controller, - consumers); + struct mpfs_sys_controller *sys_controller = + container_of(kref, struct mpfs_sys_controller, consumers); mbox_free_channel(sys_controller->chan); kfree(sys_controller); @@ -102,8 +121,9 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev) return -ENOMEM; sys_controller->client.dev = dev; - sys_controller->client.rx_callback = rx_callback; + sys_controller->client.rx_callback = mpfs_sys_controller_rx_callback; sys_controller->client.tx_block = 1U; + sys_controller->client.tx_tout = msecs_to_jiffies(MPFS_SYS_CTRL_TIMEOUT_MS); sys_controller->chan = mbox_request_channel(&sys_controller->client, 0); if (IS_ERR(sys_controller->chan)) { |