1

Qualcomm driver fixes for v6.12

The Qualcomm EDAC driver's configuration of interrupts is made optional,
 to avoid violating security constriants on X Elite platform .
 
 The SCM drivers' detection mechanism for the presence of SHM bridge in QTEE,
 is corrected to handle the case where firmware successfully returns that
 the interface isn't supported.
 
 The GLINK driver and the PMIC GLINK interface is updated to handle
 buffer allocation issues during initialization of the communication
 channel.
 
 Allocation error handling in the socinfo dirver is corrected, and then
 the fix is corrected.
 -----BEGIN PGP SIGNATURE-----
 
 iQJJBAABCAAzFiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAmck/kgVHGFuZGVyc3Nv
 bkBrZXJuZWwub3JnAAoJEAsfOT8Nma3FqV8QAMEYiZp4KnS6QkT4h47ET/dl3AiY
 EIyUge41uXjJYO4rK2JpYWi2Y30CXXwb0MRuhfZyI47mU2xYqP30hLEliqZLQqU3
 ulc4hmVyPeelRtpSX36UyZQWcaTcr0IyWnhnPSPoIr/WuyvFojBVucnAzHGFYHw6
 0Wl0Uwg0vaoptAXnAxC671ggkbXeUuxR1sOMnVAzAL9sUgZMAjDHg+Yc/Oz0i7KZ
 16OcOPFWhN+PegrIAPKx5J3X9PUsEoPqE83y3DdRVv62c58RU5tfhrhEIhmo3DVn
 ruTbrf1vV6cE1iWfGQIxyVt0WJGnY/dZqQjQxinZF0U9dlJl5+ke9ZTsaRxF0s0J
 wejMDOoqtRbNeotLxhQAp0KbPbcUHg8kkUrYMiTZLMh4eNIEBi4yLT8KhDT7IUgT
 SEP6jK4z482xpaTrDf5hDmnIMSfAO9fC50QiUMc8eNGL84XYIJgcYfi+LAP7TSiV
 wP6PI1moQcSvq034csy4AfHlsULxMdqzqh86N4DSdkoa/om2JRiYIXfTkZOteOEg
 GR4gPYigdBV8X4jj4XDiRbk+hbf+bbc6qet0HKvBPjYcKyvpH+SEVMsuxzAO8ybP
 RjP5pDrOSb7mLlx/q8RBUwyuVWk6gtDhL6tgvwfP+qu+dxTcHgRSqAi5BQfOWMvf
 2K4QO3/0tYunyqaf
 =H31v
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmcoyr0ACgkQYKtH/8kJ
 UiebJA/+OwoABEZcspBT92CnlAaIgIITx0znuO9srUcaiNxOTrZH2+T6z+sKHvOV
 bfhj0JZyK0Qk6sxU9PoczIXb2Xc42lemkZwL6TfDjQlOI10mvfTOgnIFPldG1RIp
 FcFjI3Tb6SKqh9GxDm5qLdxFn8ZoGKTLtUpP3FuV6lQNpiS7jLJILSNFXbVVMnk/
 U2HY76YQ8u2DPk5ZXmjrw49NRDvQ22ufwxJJctE0fvVyr+AUhTFBHH9h6fo3RxbC
 4IMCmEfVLnJ+ye9CqB4ahkcbu4gwzzU0eRpMb7mZ2GhufuCjgfBYA4U2XZhdEv0w
 9GenVlPr0Hs1dtpUBxvfNf0kJ2uyti4UGkW7gn8+m/sl73bMVIGPX72rxdk3vbir
 yztmdl3Nya0Nh9fPJxwP4BT6JsMshsz0POzvIOqeRTUw9yKD+wIQg9a+cwWWqdlu
 jNvBGprW7MS03uQWIWYTGkjqDsStZVJaFO//PHx+ZZ0eY/H2Lminf3GL2tsAYUtE
 pIVsS4NUcCygEELb7cEbi+S9EMkgQZPd71VAex9bjKNquBs60fSU1GZr3oOuHluv
 2XI2O+FPwdTH+yAXzqRlCj5Rczum0joa9q2lHW7hs/h7AKVSNCfzj+0YjDFIhu2E
 BnS0nbwm5axYm7vsnfA4O4QkE6AtGlRpmVfiumLg/Vif8KsA3N8=
 =2qZ7
 -----END PGP SIGNATURE-----

Merge tag 'qcom-drivers-fixes-for-6.12' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/fixes

Qualcomm driver fixes for v6.12

The Qualcomm EDAC driver's configuration of interrupts is made optional,
to avoid violating security constriants on X Elite platform .

The SCM drivers' detection mechanism for the presence of SHM bridge in QTEE,
is corrected to handle the case where firmware successfully returns that
the interface isn't supported.

The GLINK driver and the PMIC GLINK interface is updated to handle
buffer allocation issues during initialization of the communication
channel.

Allocation error handling in the socinfo dirver is corrected, and then
the fix is corrected.

* tag 'qcom-drivers-fixes-for-6.12' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux:
  soc: qcom: pmic_glink: Handle GLINK intent allocation rejections
  rpmsg: glink: Handle rejected intent request better
  soc: qcom: socinfo: fix revision check in qcom_socinfo_probe()
  firmware: qcom: scm: Return -EOPNOTSUPP for unsupported SHM bridge enabling
  EDAC/qcom: Make irq configuration optional
  firmware: qcom: scm: fix a NULL-pointer dereference
  firmware: qcom: scm: suppress download mode error
  soc: qcom: Add check devm_kasprintf() returned value
  MAINTAINERS: Qualcomm SoC: Match reserved-memory bindings

Link: https://lore.kernel.org/r/20241101161455.746290-1-andersson@kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2024-11-04 14:22:53 +01:00
commit bbfbb57958
8 changed files with 61 additions and 14 deletions

View File

@ -2852,7 +2852,7 @@ F: Documentation/devicetree/bindings/arm/qcom.yaml
F: Documentation/devicetree/bindings/bus/qcom* F: Documentation/devicetree/bindings/bus/qcom*
F: Documentation/devicetree/bindings/cache/qcom,llcc.yaml F: Documentation/devicetree/bindings/cache/qcom,llcc.yaml
F: Documentation/devicetree/bindings/firmware/qcom,scm.yaml F: Documentation/devicetree/bindings/firmware/qcom,scm.yaml
F: Documentation/devicetree/bindings/reserved-memory/qcom F: Documentation/devicetree/bindings/reserved-memory/qcom*
F: Documentation/devicetree/bindings/soc/qcom/ F: Documentation/devicetree/bindings/soc/qcom/
F: arch/arm/boot/dts/qcom/ F: arch/arm/boot/dts/qcom/
F: arch/arm/configs/qcom_defconfig F: arch/arm/configs/qcom_defconfig

View File

@ -342,9 +342,11 @@ static int qcom_llcc_edac_probe(struct platform_device *pdev)
int ecc_irq; int ecc_irq;
int rc; int rc;
rc = qcom_llcc_core_setup(llcc_driv_data, llcc_driv_data->bcast_regmap); if (!llcc_driv_data->ecc_irq_configured) {
if (rc) rc = qcom_llcc_core_setup(llcc_driv_data, llcc_driv_data->bcast_regmap);
return rc; if (rc)
return rc;
}
/* Allocate edac control info */ /* Allocate edac control info */
edev_ctl = edac_device_alloc_ctl_info(0, "qcom-llcc", 1, "bank", edev_ctl = edac_device_alloc_ctl_info(0, "qcom-llcc", 1, "bank",

View File

@ -112,6 +112,7 @@ enum qcom_scm_qseecom_tz_cmd_info {
}; };
#define QSEECOM_MAX_APP_NAME_SIZE 64 #define QSEECOM_MAX_APP_NAME_SIZE 64
#define SHMBRIDGE_RESULT_NOTSUPP 4
/* Each bit configures cold/warm boot address for one of the 4 CPUs */ /* Each bit configures cold/warm boot address for one of the 4 CPUs */
static const u8 qcom_scm_cpu_cold_bits[QCOM_SCM_BOOT_MAX_CPUS] = { static const u8 qcom_scm_cpu_cold_bits[QCOM_SCM_BOOT_MAX_CPUS] = {
@ -216,7 +217,7 @@ static DEFINE_SPINLOCK(scm_query_lock);
struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void) struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void)
{ {
return __scm->mempool; return __scm ? __scm->mempool : NULL;
} }
static enum qcom_scm_convention __get_convention(void) static enum qcom_scm_convention __get_convention(void)
@ -545,7 +546,7 @@ static void qcom_scm_set_download_mode(u32 dload_mode)
} else if (__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_BOOT, } else if (__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_BOOT,
QCOM_SCM_BOOT_SET_DLOAD_MODE)) { QCOM_SCM_BOOT_SET_DLOAD_MODE)) {
ret = __qcom_scm_set_dload_mode(__scm->dev, !!dload_mode); ret = __qcom_scm_set_dload_mode(__scm->dev, !!dload_mode);
} else { } else if (dload_mode) {
dev_err(__scm->dev, dev_err(__scm->dev,
"No available mechanism for setting download mode\n"); "No available mechanism for setting download mode\n");
} }
@ -1361,6 +1362,8 @@ EXPORT_SYMBOL_GPL(qcom_scm_lmh_dcvsh_available);
int qcom_scm_shm_bridge_enable(void) int qcom_scm_shm_bridge_enable(void)
{ {
int ret;
struct qcom_scm_desc desc = { struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_MP, .svc = QCOM_SCM_SVC_MP,
.cmd = QCOM_SCM_MP_SHM_BRIDGE_ENABLE, .cmd = QCOM_SCM_MP_SHM_BRIDGE_ENABLE,
@ -1373,7 +1376,15 @@ int qcom_scm_shm_bridge_enable(void)
QCOM_SCM_MP_SHM_BRIDGE_ENABLE)) QCOM_SCM_MP_SHM_BRIDGE_ENABLE))
return -EOPNOTSUPP; return -EOPNOTSUPP;
return qcom_scm_call(__scm->dev, &desc, &res) ?: res.result[0]; ret = qcom_scm_call(__scm->dev, &desc, &res);
if (ret)
return ret;
if (res.result[0] == SHMBRIDGE_RESULT_NOTSUPP)
return -EOPNOTSUPP;
return res.result[0];
} }
EXPORT_SYMBOL_GPL(qcom_scm_shm_bridge_enable); EXPORT_SYMBOL_GPL(qcom_scm_shm_bridge_enable);

View File

@ -1440,14 +1440,18 @@ static int qcom_glink_request_intent(struct qcom_glink *glink,
goto unlock; goto unlock;
ret = wait_event_timeout(channel->intent_req_wq, ret = wait_event_timeout(channel->intent_req_wq,
READ_ONCE(channel->intent_req_result) >= 0 && READ_ONCE(channel->intent_req_result) == 0 ||
READ_ONCE(channel->intent_received), (READ_ONCE(channel->intent_req_result) > 0 &&
READ_ONCE(channel->intent_received)) ||
glink->abort_tx,
10 * HZ); 10 * HZ);
if (!ret) { if (!ret) {
dev_err(glink->dev, "intent request timed out\n"); dev_err(glink->dev, "intent request timed out\n");
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
} else if (glink->abort_tx) {
ret = -ECANCELED;
} else { } else {
ret = READ_ONCE(channel->intent_req_result) ? 0 : -ECANCELED; ret = READ_ONCE(channel->intent_req_result) ? 0 : -EAGAIN;
} }
unlock: unlock:

View File

@ -139,6 +139,7 @@ struct qcom_llcc_config {
int size; int size;
bool need_llcc_cfg; bool need_llcc_cfg;
bool no_edac; bool no_edac;
bool irq_configured;
}; };
struct qcom_sct_config { struct qcom_sct_config {
@ -718,6 +719,7 @@ static const struct qcom_llcc_config x1e80100_cfg[] = {
.need_llcc_cfg = true, .need_llcc_cfg = true,
.reg_offset = llcc_v2_1_reg_offset, .reg_offset = llcc_v2_1_reg_offset,
.edac_reg_offset = &llcc_v2_1_edac_reg_offset, .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
.irq_configured = true,
}, },
}; };
@ -1345,6 +1347,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
drv_data->cfg = llcc_cfg; drv_data->cfg = llcc_cfg;
drv_data->cfg_size = sz; drv_data->cfg_size = sz;
drv_data->edac_reg_offset = cfg->edac_reg_offset; drv_data->edac_reg_offset = cfg->edac_reg_offset;
drv_data->ecc_irq_configured = cfg->irq_configured;
mutex_init(&drv_data->lock); mutex_init(&drv_data->lock);
platform_set_drvdata(pdev, drv_data); platform_set_drvdata(pdev, drv_data);

View File

@ -4,6 +4,7 @@
* Copyright (c) 2022, Linaro Ltd * Copyright (c) 2022, Linaro Ltd
*/ */
#include <linux/auxiliary_bus.h> #include <linux/auxiliary_bus.h>
#include <linux/delay.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
@ -13,6 +14,8 @@
#include <linux/soc/qcom/pmic_glink.h> #include <linux/soc/qcom/pmic_glink.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#define PMIC_GLINK_SEND_TIMEOUT (5 * HZ)
enum { enum {
PMIC_GLINK_CLIENT_BATT = 0, PMIC_GLINK_CLIENT_BATT = 0,
PMIC_GLINK_CLIENT_ALTMODE, PMIC_GLINK_CLIENT_ALTMODE,
@ -112,13 +115,29 @@ EXPORT_SYMBOL_GPL(pmic_glink_client_register);
int pmic_glink_send(struct pmic_glink_client *client, void *data, size_t len) int pmic_glink_send(struct pmic_glink_client *client, void *data, size_t len)
{ {
struct pmic_glink *pg = client->pg; struct pmic_glink *pg = client->pg;
bool timeout_reached = false;
unsigned long start;
int ret; int ret;
mutex_lock(&pg->state_lock); mutex_lock(&pg->state_lock);
if (!pg->ept) if (!pg->ept) {
ret = -ECONNRESET; ret = -ECONNRESET;
else } else {
ret = rpmsg_send(pg->ept, data, len); start = jiffies;
for (;;) {
ret = rpmsg_send(pg->ept, data, len);
if (ret != -EAGAIN)
break;
if (timeout_reached) {
ret = -ETIMEDOUT;
break;
}
usleep_range(1000, 5000);
timeout_reached = time_after(jiffies, start + PMIC_GLINK_SEND_TIMEOUT);
}
}
mutex_unlock(&pg->state_lock); mutex_unlock(&pg->state_lock);
return ret; return ret;

View File

@ -786,10 +786,16 @@ static int qcom_socinfo_probe(struct platform_device *pdev)
qs->attr.revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u.%u", qs->attr.revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u.%u",
SOCINFO_MAJOR(le32_to_cpu(info->ver)), SOCINFO_MAJOR(le32_to_cpu(info->ver)),
SOCINFO_MINOR(le32_to_cpu(info->ver))); SOCINFO_MINOR(le32_to_cpu(info->ver)));
if (offsetof(struct socinfo, serial_num) <= item_size) if (!qs->attr.soc_id || !qs->attr.revision)
return -ENOMEM;
if (offsetof(struct socinfo, serial_num) <= item_size) {
qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL, qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"%u", "%u",
le32_to_cpu(info->serial_num)); le32_to_cpu(info->serial_num));
if (!qs->attr.serial_number)
return -ENOMEM;
}
qs->soc_dev = soc_device_register(&qs->attr); qs->soc_dev = soc_device_register(&qs->attr);
if (IS_ERR(qs->soc_dev)) if (IS_ERR(qs->soc_dev))

View File

@ -125,6 +125,7 @@ struct llcc_edac_reg_offset {
* @num_banks: Number of llcc banks * @num_banks: Number of llcc banks
* @bitmap: Bit map to track the active slice ids * @bitmap: Bit map to track the active slice ids
* @ecc_irq: interrupt for llcc cache error detection and reporting * @ecc_irq: interrupt for llcc cache error detection and reporting
* @ecc_irq_configured: 'True' if firmware has already configured the irq propagation
* @version: Indicates the LLCC version * @version: Indicates the LLCC version
*/ */
struct llcc_drv_data { struct llcc_drv_data {
@ -139,6 +140,7 @@ struct llcc_drv_data {
u32 num_banks; u32 num_banks;
unsigned long *bitmap; unsigned long *bitmap;
int ecc_irq; int ecc_irq;
bool ecc_irq_configured;
u32 version; u32 version;
}; };