Skip to content

Commit dc3f4e7

Browse files
Bartosz Golaszewskiandersson
authored andcommitted
firmware: qcom: scm: take struct device as argument in SHM bridge enable
qcom_scm_shm_bridge_enable() is used early in the SCM initialization routine. It makes an SCM call and so expects the internal __scm pointer in the SCM driver to be assigned. For this reason the tzmem memory pool is allocated *after* this pointer is assigned. However, this can lead to a crash if another consumer of the SCM API makes a call using the memory pool between the assignment of the __scm pointer and the initialization of the tzmem memory pool. As qcom_scm_shm_bridge_enable() is a special case, not meant to be called by ordinary users, pull it into the local SCM header. Make it take struct device as argument. This is the device that will be used to make the SCM call as opposed to the global __scm pointer. This will allow us to move the tzmem initialization *before* the __scm assignment in the core SCM driver. Signed-off-by: Bartosz Golaszewski <[email protected]> Reviewed-by: Konrad Dybcio <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bjorn Andersson <[email protected]>
1 parent 23972da commit dc3f4e7

File tree

4 files changed

+12
-5
lines changed

4 files changed

+12
-5
lines changed

drivers/firmware/qcom/qcom_scm.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,7 +1603,13 @@ bool qcom_scm_lmh_dcvsh_available(void)
16031603
}
16041604
EXPORT_SYMBOL_GPL(qcom_scm_lmh_dcvsh_available);
16051605

1606-
int qcom_scm_shm_bridge_enable(void)
1606+
/*
1607+
* This is only supposed to be called once by the TZMem module. It takes the
1608+
* SCM struct device as argument and uses it to pass the call as at the time
1609+
* the SHM Bridge is enabled, the SCM is not yet fully set up and doesn't
1610+
* accept global user calls. Don't try to use the __scm pointer here.
1611+
*/
1612+
int qcom_scm_shm_bridge_enable(struct device *scm_dev)
16071613
{
16081614
int ret;
16091615

@@ -1615,11 +1621,11 @@ int qcom_scm_shm_bridge_enable(void)
16151621

16161622
struct qcom_scm_res res;
16171623

1618-
if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_MP,
1624+
if (!__qcom_scm_is_call_available(scm_dev, QCOM_SCM_SVC_MP,
16191625
QCOM_SCM_MP_SHM_BRIDGE_ENABLE))
16201626
return -EOPNOTSUPP;
16211627

1622-
ret = qcom_scm_call(__scm->dev, &desc, &res);
1628+
ret = qcom_scm_call(scm_dev, &desc, &res);
16231629

16241630
if (ret)
16251631
return ret;

drivers/firmware/qcom/qcom_scm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
8383
struct qcom_scm_res *res);
8484

8585
struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void);
86+
int qcom_scm_shm_bridge_enable(struct device *scm_dev);
8687

8788
#define QCOM_SCM_SVC_BOOT 0x01
8889
#define QCOM_SCM_BOOT_SET_ADDR 0x01

drivers/firmware/qcom/qcom_tzmem.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/spinlock.h>
2121
#include <linux/types.h>
2222

23+
#include "qcom_scm.h"
2324
#include "qcom_tzmem.h"
2425

2526
struct qcom_tzmem_area {
@@ -94,7 +95,7 @@ static int qcom_tzmem_init(void)
9495
goto notsupp;
9596
}
9697

97-
ret = qcom_scm_shm_bridge_enable();
98+
ret = qcom_scm_shm_bridge_enable(qcom_tzmem_dev);
9899
if (ret == -EOPNOTSUPP)
99100
goto notsupp;
100101

include/linux/firmware/qcom/qcom_scm.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ bool qcom_scm_lmh_dcvsh_available(void);
148148

149149
int qcom_scm_gpu_init_regs(u32 gpu_req);
150150

151-
int qcom_scm_shm_bridge_enable(void);
152151
int qcom_scm_shm_bridge_create(u64 pfn_and_ns_perm_flags,
153152
u64 ipfn_and_s_perm_flags, u64 size_and_flags,
154153
u64 ns_vmids, u64 *handle);

0 commit comments

Comments
 (0)