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:
@@ -2852,7 +2852,7 @@ F: Documentation/devicetree/bindings/arm/qcom.yaml
|
||||
F: Documentation/devicetree/bindings/bus/qcom*
|
||||
F: Documentation/devicetree/bindings/cache/qcom,llcc.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: arch/arm/boot/dts/qcom/
|
||||
F: arch/arm/configs/qcom_defconfig
|
||||
|
||||
@@ -342,9 +342,11 @@ static int qcom_llcc_edac_probe(struct platform_device *pdev)
|
||||
int ecc_irq;
|
||||
int rc;
|
||||
|
||||
rc = qcom_llcc_core_setup(llcc_driv_data, llcc_driv_data->bcast_regmap);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (!llcc_driv_data->ecc_irq_configured) {
|
||||
rc = qcom_llcc_core_setup(llcc_driv_data, llcc_driv_data->bcast_regmap);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Allocate edac control info */
|
||||
edev_ctl = edac_device_alloc_ctl_info(0, "qcom-llcc", 1, "bank",
|
||||
|
||||
@@ -112,6 +112,7 @@ enum qcom_scm_qseecom_tz_cmd_info {
|
||||
};
|
||||
|
||||
#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 */
|
||||
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)
|
||||
{
|
||||
return __scm->mempool;
|
||||
return __scm ? __scm->mempool : NULL;
|
||||
}
|
||||
|
||||
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,
|
||||
QCOM_SCM_BOOT_SET_DLOAD_MODE)) {
|
||||
ret = __qcom_scm_set_dload_mode(__scm->dev, !!dload_mode);
|
||||
} else {
|
||||
} else if (dload_mode) {
|
||||
dev_err(__scm->dev,
|
||||
"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 ret;
|
||||
|
||||
struct qcom_scm_desc desc = {
|
||||
.svc = QCOM_SCM_SVC_MP,
|
||||
.cmd = QCOM_SCM_MP_SHM_BRIDGE_ENABLE,
|
||||
@@ -1373,7 +1376,15 @@ int qcom_scm_shm_bridge_enable(void)
|
||||
QCOM_SCM_MP_SHM_BRIDGE_ENABLE))
|
||||
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);
|
||||
|
||||
|
||||
@@ -1440,14 +1440,18 @@ static int qcom_glink_request_intent(struct qcom_glink *glink,
|
||||
goto unlock;
|
||||
|
||||
ret = wait_event_timeout(channel->intent_req_wq,
|
||||
READ_ONCE(channel->intent_req_result) >= 0 &&
|
||||
READ_ONCE(channel->intent_received),
|
||||
READ_ONCE(channel->intent_req_result) == 0 ||
|
||||
(READ_ONCE(channel->intent_req_result) > 0 &&
|
||||
READ_ONCE(channel->intent_received)) ||
|
||||
glink->abort_tx,
|
||||
10 * HZ);
|
||||
if (!ret) {
|
||||
dev_err(glink->dev, "intent request timed out\n");
|
||||
ret = -ETIMEDOUT;
|
||||
} else if (glink->abort_tx) {
|
||||
ret = -ECANCELED;
|
||||
} else {
|
||||
ret = READ_ONCE(channel->intent_req_result) ? 0 : -ECANCELED;
|
||||
ret = READ_ONCE(channel->intent_req_result) ? 0 : -EAGAIN;
|
||||
}
|
||||
|
||||
unlock:
|
||||
|
||||
@@ -139,6 +139,7 @@ struct qcom_llcc_config {
|
||||
int size;
|
||||
bool need_llcc_cfg;
|
||||
bool no_edac;
|
||||
bool irq_configured;
|
||||
};
|
||||
|
||||
struct qcom_sct_config {
|
||||
@@ -718,6 +719,7 @@ static const struct qcom_llcc_config x1e80100_cfg[] = {
|
||||
.need_llcc_cfg = true,
|
||||
.reg_offset = llcc_v2_1_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_size = sz;
|
||||
drv_data->edac_reg_offset = cfg->edac_reg_offset;
|
||||
drv_data->ecc_irq_configured = cfg->irq_configured;
|
||||
mutex_init(&drv_data->lock);
|
||||
platform_set_drvdata(pdev, drv_data);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* Copyright (c) 2022, Linaro Ltd
|
||||
*/
|
||||
#include <linux/auxiliary_bus.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -13,6 +14,8 @@
|
||||
#include <linux/soc/qcom/pmic_glink.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#define PMIC_GLINK_SEND_TIMEOUT (5 * HZ)
|
||||
|
||||
enum {
|
||||
PMIC_GLINK_CLIENT_BATT = 0,
|
||||
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)
|
||||
{
|
||||
struct pmic_glink *pg = client->pg;
|
||||
bool timeout_reached = false;
|
||||
unsigned long start;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&pg->state_lock);
|
||||
if (!pg->ept)
|
||||
if (!pg->ept) {
|
||||
ret = -ECONNRESET;
|
||||
else
|
||||
ret = rpmsg_send(pg->ept, data, len);
|
||||
} else {
|
||||
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);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -786,10 +786,16 @@ static int qcom_socinfo_probe(struct platform_device *pdev)
|
||||
qs->attr.revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u.%u",
|
||||
SOCINFO_MAJOR(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,
|
||||
"%u",
|
||||
le32_to_cpu(info->serial_num));
|
||||
if (!qs->attr.serial_number)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
qs->soc_dev = soc_device_register(&qs->attr);
|
||||
if (IS_ERR(qs->soc_dev))
|
||||
|
||||
@@ -125,6 +125,7 @@ struct llcc_edac_reg_offset {
|
||||
* @num_banks: Number of llcc banks
|
||||
* @bitmap: Bit map to track the active slice ids
|
||||
* @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
|
||||
*/
|
||||
struct llcc_drv_data {
|
||||
@@ -139,6 +140,7 @@ struct llcc_drv_data {
|
||||
u32 num_banks;
|
||||
unsigned long *bitmap;
|
||||
int ecc_irq;
|
||||
bool ecc_irq_configured;
|
||||
u32 version;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user