Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: qcom: rmtfs: Optionally map RMTFS to more VMs

Some SoCs require that RMTFS is also mapped to the NAV VM. Trying to
power on the modem without that results in the whole platform
crashing and forces a hard reboot within about 2 seconds. Add support
for mapping the region to additional VMs, such as NAV to open a path
towards enabling modem on such platforms.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
[Konrad: reword, make conditional and flexible, add a define for NAV VMID]
Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
Link: https://lore.kernel.org/r/20230109130523.298971-2-konrad.dybcio@linaro.org

authored by

Loic Poulain and committed by
Bjorn Andersson
e656cd0b da0d37e4

+23 -7
+22 -7
drivers/soc/qcom/rmtfs_mem.c
··· 17 17 #include <linux/qcom_scm.h> 18 18 19 19 #define QCOM_RMTFS_MEM_DEV_MAX (MINORMASK + 1) 20 + #define NUM_MAX_VMIDS 2 20 21 21 22 static dev_t qcom_rmtfs_mem_major; 22 23 ··· 172 171 static int qcom_rmtfs_mem_probe(struct platform_device *pdev) 173 172 { 174 173 struct device_node *node = pdev->dev.of_node; 175 - struct qcom_scm_vmperm perms[2]; 174 + struct qcom_scm_vmperm perms[NUM_MAX_VMIDS + 1]; 176 175 struct reserved_mem *rmem; 177 176 struct qcom_rmtfs_mem *rmtfs_mem; 178 177 u32 client_id; 179 - u32 vmid; 180 - int ret; 178 + u32 num_vmids, vmid[NUM_MAX_VMIDS]; 179 + int ret, i; 181 180 182 181 rmem = of_reserved_mem_lookup(node); 183 182 if (!rmem) { ··· 227 226 goto put_device; 228 227 } 229 228 230 - ret = of_property_read_u32(node, "qcom,vmid", &vmid); 229 + num_vmids = of_property_count_u32_elems(node, "qcom,vmid"); 230 + if (num_vmids < 0) { 231 + dev_err(&pdev->dev, "failed to count qcom,vmid elements: %d\n", ret); 232 + goto remove_cdev; 233 + } else if (num_vmids > NUM_MAX_VMIDS) { 234 + dev_warn(&pdev->dev, 235 + "too many VMIDs (%d) specified! Only mapping first %d entries\n", 236 + num_vmids, NUM_MAX_VMIDS); 237 + num_vmids = NUM_MAX_VMIDS; 238 + } 239 + 240 + ret = of_property_read_u32_array(node, "qcom,vmid", vmid, num_vmids); 231 241 if (ret < 0 && ret != -EINVAL) { 232 242 dev_err(&pdev->dev, "failed to parse qcom,vmid\n"); 233 243 goto remove_cdev; ··· 250 238 251 239 perms[0].vmid = QCOM_SCM_VMID_HLOS; 252 240 perms[0].perm = QCOM_SCM_PERM_RW; 253 - perms[1].vmid = vmid; 254 - perms[1].perm = QCOM_SCM_PERM_RW; 241 + 242 + for (i = 0; i < num_vmids; i++) { 243 + perms[i + 1].vmid = vmid[i]; 244 + perms[i + 1].perm = QCOM_SCM_PERM_RW; 245 + } 255 246 256 247 rmtfs_mem->perms = BIT(QCOM_SCM_VMID_HLOS); 257 248 ret = qcom_scm_assign_mem(rmtfs_mem->addr, rmtfs_mem->size, 258 - &rmtfs_mem->perms, perms, 2); 249 + &rmtfs_mem->perms, perms, num_vmids + 1); 259 250 if (ret < 0) { 260 251 dev_err(&pdev->dev, "assign memory failed\n"); 261 252 goto remove_cdev;
+1
include/linux/qcom_scm.h
··· 55 55 #define QCOM_SCM_VMID_MSS_MSA 0xF 56 56 #define QCOM_SCM_VMID_WLAN 0x18 57 57 #define QCOM_SCM_VMID_WLAN_CE 0x19 58 + #define QCOM_SCM_VMID_NAV 0x2B 58 59 #define QCOM_SCM_PERM_READ 0x4 59 60 #define QCOM_SCM_PERM_WRITE 0x2 60 61 #define QCOM_SCM_PERM_EXEC 0x1