From: Greg Kroah-Hartman Date: Fri, 15 Apr 2022 10:29:48 +0000 (+0200) Subject: 5.15-stable patches X-Git-Tag: v4.19.238~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9e948c16ad302dc57a63ee3e2c2d78f32673ca37;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: dt-bindings-net-qcom-ipa-add-optional-qcom-qmp-property.patch net-ipa-request-ipa-register-values-be-retained.patch soc-qcom-aoss-expose-send-for-generic-usecase.patch --- diff --git a/queue-5.15/dt-bindings-net-qcom-ipa-add-optional-qcom-qmp-property.patch b/queue-5.15/dt-bindings-net-qcom-ipa-add-optional-qcom-qmp-property.patch new file mode 100644 index 00000000000..7af34b0b282 --- /dev/null +++ b/queue-5.15/dt-bindings-net-qcom-ipa-add-optional-qcom-qmp-property.patch @@ -0,0 +1,43 @@ +From ac62a0174d62ae0f4447c0c8cf35a8e5d793df56 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Tue, 1 Feb 2022 09:02:04 -0600 +Subject: dt-bindings: net: qcom,ipa: add optional qcom,qmp property + +From: Alex Elder + +commit ac62a0174d62ae0f4447c0c8cf35a8e5d793df56 upstream. + +For some systems, the IPA driver must make a request to ensure that +its registers are retained across power collapse of the IPA hardware. +On such systems, we'll use the existence of the "qcom,qmp" property +as a signal that this request is required. + +Signed-off-by: Alex Elder +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/devicetree/bindings/net/qcom,ipa.yaml | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/Documentation/devicetree/bindings/net/qcom,ipa.yaml ++++ b/Documentation/devicetree/bindings/net/qcom,ipa.yaml +@@ -106,6 +106,10 @@ properties: + - const: imem + - const: config + ++ qcom,qmp: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: phandle to the AOSS side-channel message RAM ++ + qcom,smem-states: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: State bits used in by the AP to signal the modem. +@@ -221,6 +225,8 @@ examples: + "imem", + "config"; + ++ qcom,qmp = <&aoss_qmp>; ++ + qcom,smem-states = <&ipa_smp2p_out 0>, + <&ipa_smp2p_out 1>; + qcom,smem-state-names = "ipa-clock-enabled-valid", diff --git a/queue-5.15/net-ipa-request-ipa-register-values-be-retained.patch b/queue-5.15/net-ipa-request-ipa-register-values-be-retained.patch new file mode 100644 index 00000000000..36ae63b44be --- /dev/null +++ b/queue-5.15/net-ipa-request-ipa-register-values-be-retained.patch @@ -0,0 +1,176 @@ +From 34a081761e4e3c35381cbfad609ebae2962fe2f8 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Tue, 1 Feb 2022 09:02:05 -0600 +Subject: net: ipa: request IPA register values be retained + +From: Alex Elder + +commit 34a081761e4e3c35381cbfad609ebae2962fe2f8 upstream. + +In some cases, the IPA hardware needs to request the always-on +subsystem (AOSS) to coordinate with the IPA microcontroller to +retain IPA register values at power collapse. This is done by +issuing a QMP request to the AOSS microcontroller. A similar +request ondoes that request. + +We must get and hold the "QMP" handle early, because we might get +back EPROBE_DEFER for that. But the actual request should be sent +while we know the IPA clock is active, and when we know the +microcontroller is operational. + +Fixes: 1aac309d3207 ("net: ipa: use autosuspend") +Signed-off-by: Alex Elder +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ipa/ipa_power.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ + drivers/net/ipa/ipa_power.h | 7 +++++ + drivers/net/ipa/ipa_uc.c | 5 ++++ + 3 files changed, 64 insertions(+) + +--- a/drivers/net/ipa/ipa_power.c ++++ b/drivers/net/ipa/ipa_power.c +@@ -11,6 +11,8 @@ + #include + #include + ++#include "linux/soc/qcom/qcom_aoss.h" ++ + #include "ipa.h" + #include "ipa_power.h" + #include "ipa_endpoint.h" +@@ -64,6 +66,7 @@ enum ipa_power_flag { + * struct ipa_power - IPA power management information + * @dev: IPA device pointer + * @core: IPA core clock ++ * @qmp: QMP handle for AOSS communication + * @spinlock: Protects modem TX queue enable/disable + * @flags: Boolean state flags + * @interconnect_count: Number of elements in interconnect[] +@@ -72,6 +75,7 @@ enum ipa_power_flag { + struct ipa_power { + struct device *dev; + struct clk *core; ++ struct qmp *qmp; + spinlock_t spinlock; /* used with STOPPED/STARTED power flags */ + DECLARE_BITMAP(flags, IPA_POWER_FLAG_COUNT); + u32 interconnect_count; +@@ -382,6 +386,47 @@ void ipa_power_modem_queue_active(struct + clear_bit(IPA_POWER_FLAG_STARTED, ipa->power->flags); + } + ++static int ipa_power_retention_init(struct ipa_power *power) ++{ ++ struct qmp *qmp = qmp_get(power->dev); ++ ++ if (IS_ERR(qmp)) { ++ if (PTR_ERR(qmp) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ ++ /* We assume any other error means it's not defined/needed */ ++ qmp = NULL; ++ } ++ power->qmp = qmp; ++ ++ return 0; ++} ++ ++static void ipa_power_retention_exit(struct ipa_power *power) ++{ ++ qmp_put(power->qmp); ++ power->qmp = NULL; ++} ++ ++/* Control register retention on power collapse */ ++void ipa_power_retention(struct ipa *ipa, bool enable) ++{ ++ static const char fmt[] = "{ class: bcm, res: ipa_pc, val: %c }"; ++ struct ipa_power *power = ipa->power; ++ char buf[36]; /* Exactly enough for fmt[]; size a multiple of 4 */ ++ int ret; ++ ++ if (!power->qmp) ++ return; /* Not needed on this platform */ ++ ++ (void)snprintf(buf, sizeof(buf), fmt, enable ? '1' : '0'); ++ ++ ret = qmp_send(power->qmp, buf, sizeof(buf)); ++ if (ret) ++ dev_err(power->dev, "error %d sending QMP %sable request\n", ++ ret, enable ? "en" : "dis"); ++} ++ + int ipa_power_setup(struct ipa *ipa) + { + int ret; +@@ -438,12 +483,18 @@ ipa_power_init(struct device *dev, const + if (ret) + goto err_kfree; + ++ ret = ipa_power_retention_init(power); ++ if (ret) ++ goto err_interconnect_exit; ++ + pm_runtime_set_autosuspend_delay(dev, IPA_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(dev); + pm_runtime_enable(dev); + + return power; + ++err_interconnect_exit: ++ ipa_interconnect_exit(power); + err_kfree: + kfree(power); + err_clk_put: +@@ -460,6 +511,7 @@ void ipa_power_exit(struct ipa_power *po + + pm_runtime_disable(dev); + pm_runtime_dont_use_autosuspend(dev); ++ ipa_power_retention_exit(power); + ipa_interconnect_exit(power); + kfree(power); + clk_put(clk); +--- a/drivers/net/ipa/ipa_power.h ++++ b/drivers/net/ipa/ipa_power.h +@@ -41,6 +41,13 @@ void ipa_power_modem_queue_wake(struct i + void ipa_power_modem_queue_active(struct ipa *ipa); + + /** ++ * ipa_power_retention() - Control register retention on power collapse ++ * @ipa: IPA pointer ++ * @enable: Whether retention should be enabled or disabled ++ */ ++void ipa_power_retention(struct ipa *ipa, bool enable); ++ ++/** + * ipa_power_setup() - Set up IPA power management + * @ipa: IPA pointer + * +--- a/drivers/net/ipa/ipa_uc.c ++++ b/drivers/net/ipa/ipa_uc.c +@@ -11,6 +11,7 @@ + + #include "ipa.h" + #include "ipa_uc.h" ++#include "ipa_power.h" + + /** + * DOC: The IPA embedded microcontroller +@@ -154,6 +155,7 @@ static void ipa_uc_response_hdlr(struct + case IPA_UC_RESPONSE_INIT_COMPLETED: + if (ipa->uc_powered) { + ipa->uc_loaded = true; ++ ipa_power_retention(ipa, true); + pm_runtime_mark_last_busy(dev); + (void)pm_runtime_put_autosuspend(dev); + ipa->uc_powered = false; +@@ -184,6 +186,9 @@ void ipa_uc_deconfig(struct ipa *ipa) + + ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_UC_1); + ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_UC_0); ++ if (ipa->uc_loaded) ++ ipa_power_retention(ipa, false); ++ + if (!ipa->uc_powered) + return; + diff --git a/queue-5.15/series b/queue-5.15/series index bd86506e50a..1fee074ef5e 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -9,3 +9,6 @@ acpi-processor-idle-fix-lockup-regression-on-32-bit-thinkpad-t40.patch btrfs-remove-unused-parameter-nr_pages-in-add_ra_bio_pages.patch btrfs-remove-no-longer-used-counter-when-reading-data-page.patch btrfs-remove-unused-variable-in-btrfs_-start-write-_dirty_block_groups.patch +soc-qcom-aoss-expose-send-for-generic-usecase.patch +dt-bindings-net-qcom-ipa-add-optional-qcom-qmp-property.patch +net-ipa-request-ipa-register-values-be-retained.patch diff --git a/queue-5.15/soc-qcom-aoss-expose-send-for-generic-usecase.patch b/queue-5.15/soc-qcom-aoss-expose-send-for-generic-usecase.patch new file mode 100644 index 00000000000..f0d295f367e --- /dev/null +++ b/queue-5.15/soc-qcom-aoss-expose-send-for-generic-usecase.patch @@ -0,0 +1,166 @@ +From 8c75d585b931ac874fbe4ee5a8f1811d20c2817f Mon Sep 17 00:00:00 2001 +From: Deepak Kumar Singh +Date: Tue, 31 Aug 2021 20:00:27 +0530 +Subject: soc: qcom: aoss: Expose send for generic usecase + +From: Deepak Kumar Singh + +commit 8c75d585b931ac874fbe4ee5a8f1811d20c2817f upstream. + +Not all upcoming usecases will have an interface to allow the aoss +driver to hook onto. Expose the send api and create a get function to +enable drivers to send their own messages to aoss. + +Signed-off-by: Chris Lew +Signed-off-by: Deepak Kumar Singh +Reviewed-by: Stephen Boyd +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/1630420228-31075-2-git-send-email-deesin@codeaurora.org +Signed-off-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + drivers/soc/qcom/qcom_aoss.c | 54 ++++++++++++++++++++++++++++++++++++- + include/linux/soc/qcom/qcom_aoss.h | 38 ++++++++++++++++++++++++++ + 2 files changed, 91 insertions(+), 1 deletion(-) + create mode 100644 include/linux/soc/qcom/qcom_aoss.h + +--- a/drivers/soc/qcom/qcom_aoss.c ++++ b/drivers/soc/qcom/qcom_aoss.c +@@ -8,10 +8,12 @@ + #include + #include + #include ++#include + #include + #include + #include + #include ++#include + + #define QMP_DESC_MAGIC 0x0 + #define QMP_DESC_VERSION 0x4 +@@ -223,11 +225,14 @@ static bool qmp_message_empty(struct qmp + * + * Return: 0 on success, negative errno on failure + */ +-static int qmp_send(struct qmp *qmp, const void *data, size_t len) ++int qmp_send(struct qmp *qmp, const void *data, size_t len) + { + long time_left; + int ret; + ++ if (WARN_ON(IS_ERR_OR_NULL(qmp) || !data)) ++ return -EINVAL; ++ + if (WARN_ON(len + sizeof(u32) > qmp->size)) + return -EINVAL; + +@@ -261,6 +266,7 @@ static int qmp_send(struct qmp *qmp, con + + return ret; + } ++EXPORT_SYMBOL(qmp_send); + + static int qmp_qdss_clk_prepare(struct clk_hw *hw) + { +@@ -519,6 +525,51 @@ static void qmp_cooling_devices_remove(s + thermal_cooling_device_unregister(qmp->cooling_devs[i].cdev); + } + ++/** ++ * qmp_get() - get a qmp handle from a device ++ * @dev: client device pointer ++ * ++ * Return: handle to qmp device on success, ERR_PTR() on failure ++ */ ++struct qmp *qmp_get(struct device *dev) ++{ ++ struct platform_device *pdev; ++ struct device_node *np; ++ struct qmp *qmp; ++ ++ if (!dev || !dev->of_node) ++ return ERR_PTR(-EINVAL); ++ ++ np = of_parse_phandle(dev->of_node, "qcom,qmp", 0); ++ if (!np) ++ return ERR_PTR(-ENODEV); ++ ++ pdev = of_find_device_by_node(np); ++ of_node_put(np); ++ if (!pdev) ++ return ERR_PTR(-EINVAL); ++ ++ qmp = platform_get_drvdata(pdev); ++ ++ return qmp ? qmp : ERR_PTR(-EPROBE_DEFER); ++} ++EXPORT_SYMBOL(qmp_get); ++ ++/** ++ * qmp_put() - release a qmp handle ++ * @qmp: qmp handle obtained from qmp_get() ++ */ ++void qmp_put(struct qmp *qmp) ++{ ++ /* ++ * Match get_device() inside of_find_device_by_node() in ++ * qmp_get() ++ */ ++ if (!IS_ERR_OR_NULL(qmp)) ++ put_device(qmp->dev); ++} ++EXPORT_SYMBOL(qmp_put); ++ + static int qmp_probe(struct platform_device *pdev) + { + struct resource *res; +@@ -615,6 +666,7 @@ static struct platform_driver qmp_driver + .driver = { + .name = "qcom_aoss_qmp", + .of_match_table = qmp_dt_match, ++ .suppress_bind_attrs = true, + }, + .probe = qmp_probe, + .remove = qmp_remove, +--- /dev/null ++++ b/include/linux/soc/qcom/qcom_aoss.h +@@ -0,0 +1,38 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2021, The Linux Foundation. All rights reserved. ++ */ ++ ++#ifndef __QCOM_AOSS_H__ ++#define __QCOM_AOSS_H__ ++ ++#include ++#include ++ ++struct qmp; ++ ++#if IS_ENABLED(CONFIG_QCOM_AOSS_QMP) ++ ++int qmp_send(struct qmp *qmp, const void *data, size_t len); ++struct qmp *qmp_get(struct device *dev); ++void qmp_put(struct qmp *qmp); ++ ++#else ++ ++static inline int qmp_send(struct qmp *qmp, const void *data, size_t len) ++{ ++ return -ENODEV; ++} ++ ++static inline struct qmp *qmp_get(struct device *dev) ++{ ++ return ERR_PTR(-ENODEV); ++} ++ ++static inline void qmp_put(struct qmp *qmp) ++{ ++} ++ ++#endif ++ ++#endif