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

Merge tag 'rproc-v5.1' of git://github.com/andersson/remoteproc

Pull remoteproc updates from Bjorn Andersson:
"This contains the last patches in Loic's remoteproc resource table
handling changes, a number of updates to documentation, support for
invoking the crash handler (for testing purposes), a fix for the
handling of virtio devices during recovery, performance state votes in
Qualcomm modem driver, support for specifying board specific firmware
path for Qualcomm modem driver and improved support for graceful
shutdown of Qualcomm remoteprocs"

* tag 'rproc-v5.1' of git://github.com/andersson/remoteproc: (33 commits)
remoteproc: fix for "dma-mapping: remove the DMA_MEMORY_EXCLUSIVE flag"
remoteproc: fix rproc_check_carveout_da() returned error and comments
remoteproc: fix trace buffer va initialization
remoteproc: fix rproc_alloc_carveout() for rproc with iommu domain
remoteproc: add warning on resource table cast
remoteproc: fix rproc_alloc_carveout() bad variable cast
remoteproc: fix rproc_da_to_va in case of unallocated carveout
remoteproc: correct rproc_mem_entry_init() comments
remoteproc: fix recovery procedure
rpmsg: virtio: change header file sort style
rpmsg: virtio: allocate buffer from parent
remoteproc: st: add reserved memory support
remoteproc: create vdev subdevice with specific dma memory pool
remoteproc: q6v5_adsp: Remove voting for lpass_aon clock
dt-binding: remoteproc: Remove lpass_aon clock from adsp pil clock list
remoteproc: q6v5-mss: Active powerdomain for SDM845
remoteproc: q6v5-mss: Vote for rpmh power domains
remoteproc: qcom: Add support for parsing fw dt bindings
remoteproc: qcom_q6v5: don't auto boot remote processor
remoteproc: qcom: Wait for shutdown-ack/ind on sysmon shutdown
...

+706 -120
+2 -3
Documentation/devicetree/bindings/remoteproc/qcom,adsp-pil.txt
··· 35 35 Value type: <stringlist> 36 36 Definition: List of clock input name strings sorted in the same 37 37 order as the clocks property. Definition must have 38 - "xo", "sway_cbcr", "lpass_aon", "lpass_ahbs_aon_cbcr", 38 + "xo", "sway_cbcr", "lpass_ahbs_aon_cbcr", 39 39 "lpass_ahbm_aon_cbcr", "qdsp6ss_xo", "qdsp6ss_sleep" 40 40 and "qdsp6ss_core". 41 41 ··· 100 100 101 101 clocks = <&rpmhcc RPMH_CXO_CLK>, 102 102 <&gcc GCC_LPASS_SWAY_CLK>, 103 - <&lpasscc LPASS_AUDIO_WRAPPER_AON_CLK>, 104 103 <&lpasscc LPASS_Q6SS_AHBS_AON_CLK>, 105 104 <&lpasscc LPASS_Q6SS_AHBM_AON_CLK>, 106 105 <&lpasscc LPASS_QDSP6SS_XO_CLK>, 107 106 <&lpasscc LPASS_QDSP6SS_SLEEP_CLK>, 108 107 <&lpasscc LPASS_QDSP6SS_CORE_CLK>; 109 - clock-names = "xo", "sway_cbcr", "lpass_aon", 108 + clock-names = "xo", "sway_cbcr", 110 109 "lpass_ahbs_aon_cbcr", 111 110 "lpass_ahbm_aon_cbcr", "qdsp6ss_xo", 112 111 "qdsp6ss_sleep", "qdsp6ss_core";
+20 -3
Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt
··· 19 19 - interrupts-extended: 20 20 Usage: required 21 21 Value type: <prop-encoded-array> 22 - Definition: must list the watchdog, fatal IRQs ready, handover and 23 - stop-ack IRQs 22 + Definition: reference to the interrupts that match interrupt-names 24 23 25 24 - interrupt-names: 26 25 Usage: required 27 26 Value type: <stringlist> 28 - Definition: must be "wdog", "fatal", "ready", "handover", "stop-ack" 27 + Definition: The interrupts needed depends on the compatible 28 + string: 29 + qcom,msm8974-adsp-pil: 30 + qcom,msm8996-adsp-pil: 31 + qcom,msm8996-slpi-pil: 32 + qcom,qcs404-adsp-pas: 33 + qcom,qcs404-cdsp-pas: 34 + qcom,sdm845-adsp-pas: 35 + qcom,sdm845-cdsp-pas: 36 + must be "wdog", "fatal", "ready", "handover", "stop-ack" 37 + qcom,qcs404-wcss-pas: 38 + must be "wdog", "fatal", "ready", "handover", "stop-ack", 39 + "shutdown-ack" 40 + 41 + - firmware-name: 42 + Usage: optional 43 + Value type: <string> 44 + Definition: must list the relative firmware image path for the 45 + Hexagon Core. 29 46 30 47 - clocks: 31 48 Usage: required
+73 -6
Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
··· 28 28 - interrupts-extended: 29 29 Usage: required 30 30 Value type: <prop-encoded-array> 31 - Definition: must list the watchdog, fatal IRQs ready, handover and 32 - stop-ack IRQs 31 + Definition: reference to the interrupts that match interrupt-names 33 32 34 33 - interrupt-names: 35 34 Usage: required 36 35 Value type: <stringlist> 37 - Definition: must be "wdog", "fatal", "ready", "handover", "stop-ack" 36 + Definition: The interrupts needed depends on the the compatible 37 + string: 38 + qcom,q6v5-pil: 39 + qcom,ipq8074-wcss-pil: 40 + qcom,msm8916-mss-pil: 41 + qcom,msm8974-mss-pil: 42 + must be "wdog", "fatal", "ready", "handover", "stop-ack" 43 + qcom,msm8996-mss-pil: 44 + qcom,sdm845-mss-pil: 45 + must be "wdog", "fatal", "ready", "handover", "stop-ack", 46 + "shutdown-ack" 47 + 48 + - firmware-name: 49 + Usage: optional 50 + Value type: <stringlist> 51 + Definition: must list the relative firmware image paths for mba and 52 + modem. They are used for booting and authenticating the 53 + Hexagon core. 38 54 39 55 - clocks: 40 56 Usage: required 41 57 Value type: <phandle> 42 - Definition: reference to the iface, bus and mem clocks to be held on 43 - behalf of the booting of the Hexagon core 58 + Definition: reference to the clocks that match clock-names 44 59 45 60 - clock-names: 46 61 Usage: required 47 62 Value type: <stringlist> 48 - Definition: must be "iface", "bus", "mem" 63 + Definition: The clocks needed depend on the compatible string: 64 + qcom,ipq8074-wcss-pil: 65 + no clock names required 66 + qcom,q6v5-pil: 67 + qcom,msm8916-mss-pil: 68 + qcom,msm8974-mss-pil: 69 + must be "iface", "bus", "mem", "xo" 70 + qcom,msm8996-mss-pil: 71 + must be "iface", "bus", "mem", "xo", "gpll0_mss", 72 + "snoc_axi", "mnoc_axi", "pnoc", "qdss" 73 + qcom,sdm845-mss-pil: 74 + must be "iface", "bus", "mem", "xo", "gpll0_mss", 75 + "snoc_axi", "mnoc_axi", "prng" 49 76 50 77 - resets: 51 78 Usage: required ··· 92 65 must be "mss_restart", "pdc_reset" for the modem 93 66 sub-system on SDM845 SoCs 94 67 68 + For the compatible strings below the following supplies are required: 69 + "qcom,q6v5-pil" 70 + "qcom,msm8916-mss-pil", 71 + - cx-supply: 72 + - mx-supply: 73 + - pll-supply: 74 + Usage: required 75 + Value type: <phandle> 76 + Definition: reference to the regulators to be held on behalf of the 77 + booting of the Hexagon core 78 + 79 + For the compatible string below the following supplies are required: 80 + "qcom,msm8974-mss-pil" 95 81 - cx-supply: 96 82 - mss-supply: 97 83 - mx-supply: ··· 113 73 Value type: <phandle> 114 74 Definition: reference to the regulators to be held on behalf of the 115 75 booting of the Hexagon core 76 + 77 + For the compatible string below the following supplies are required: 78 + "qcom,msm8996-mss-pil" 79 + - pll-supply: 80 + Usage: required 81 + Value type: <phandle> 82 + Definition: reference to the regulators to be held on behalf of the 83 + booting of the Hexagon core 84 + 85 + - power-domains: 86 + Usage: required 87 + Value type: <phandle> 88 + Definition: reference to power-domains that match power-domain-names 89 + 90 + - power-domain-names: 91 + Usage: required 92 + Value type: <stringlist> 93 + Definition: The power-domains needed depend on the compatible string: 94 + qcom,q6v5-pil: 95 + qcom,ipq8074-wcss-pil: 96 + qcom,msm8916-mss-pil: 97 + qcom,msm8974-mss-pil: 98 + no power-domain names required 99 + qcom,msm8996-mss-pil: 100 + must be "cx", "mx" 101 + qcom,sdm845-mss-pil: 102 + must be "cx", "mx", "mss", "load_state" 116 103 117 104 - qcom,smem-states: 118 105 Usage: required
+5 -1
drivers/remoteproc/qcom_q6v5_adsp.c
··· 48 48 49 49 /* list of clocks required by ADSP PIL */ 50 50 static const char * const adsp_clk_id[] = { 51 - "sway_cbcr", "lpass_aon", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr", 51 + "sway_cbcr", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr", 52 52 "qdsp6ss_xo", "qdsp6ss_sleep", "qdsp6ss_core", 53 53 }; 54 54 ··· 439 439 adsp->sysmon = qcom_add_sysmon_subdev(rproc, 440 440 desc->sysmon_name, 441 441 desc->ssctl_id); 442 + if (IS_ERR(adsp->sysmon)) { 443 + ret = PTR_ERR(adsp->sysmon); 444 + goto disable_pm; 445 + } 442 446 443 447 ret = rproc_add(rproc); 444 448 if (ret)
+194 -15
drivers/remoteproc/qcom_q6v5_mss.c
··· 25 25 #include <linux/of_address.h> 26 26 #include <linux/of_device.h> 27 27 #include <linux/platform_device.h> 28 + #include <linux/pm_domain.h> 29 + #include <linux/pm_runtime.h> 28 30 #include <linux/regmap.h> 29 31 #include <linux/regulator/consumer.h> 30 32 #include <linux/remoteproc.h> ··· 133 131 char **proxy_clk_names; 134 132 char **reset_clk_names; 135 133 char **active_clk_names; 134 + char **active_pd_names; 135 + char **proxy_pd_names; 136 136 int version; 137 137 bool need_mem_protection; 138 138 bool has_alt_reset; ··· 160 156 struct clk *active_clks[8]; 161 157 struct clk *reset_clks[4]; 162 158 struct clk *proxy_clks[4]; 159 + struct device *active_pds[1]; 160 + struct device *proxy_pds[3]; 163 161 int active_clk_count; 164 162 int reset_clk_count; 165 163 int proxy_clk_count; 164 + int active_pd_count; 165 + int proxy_pd_count; 166 166 167 167 struct reg_info active_regs[1]; 168 168 struct reg_info proxy_regs[3]; ··· 196 188 bool has_alt_reset; 197 189 int mpss_perm; 198 190 int mba_perm; 191 + const char *hexagon_mdt_image; 199 192 int version; 200 193 }; 201 194 ··· 328 319 329 320 for (i = 0; i < count; i++) 330 321 clk_disable_unprepare(clks[i]); 322 + } 323 + 324 + static int q6v5_pds_enable(struct q6v5 *qproc, struct device **pds, 325 + size_t pd_count) 326 + { 327 + int ret; 328 + int i; 329 + 330 + for (i = 0; i < pd_count; i++) { 331 + dev_pm_genpd_set_performance_state(pds[i], INT_MAX); 332 + ret = pm_runtime_get_sync(pds[i]); 333 + if (ret < 0) 334 + goto unroll_pd_votes; 335 + } 336 + 337 + return 0; 338 + 339 + unroll_pd_votes: 340 + for (i--; i >= 0; i--) { 341 + dev_pm_genpd_set_performance_state(pds[i], 0); 342 + pm_runtime_put(pds[i]); 343 + } 344 + 345 + return ret; 346 + }; 347 + 348 + static void q6v5_pds_disable(struct q6v5 *qproc, struct device **pds, 349 + size_t pd_count) 350 + { 351 + int i; 352 + 353 + for (i = 0; i < pd_count; i++) { 354 + dev_pm_genpd_set_performance_state(pds[i], 0); 355 + pm_runtime_put(pds[i]); 356 + } 331 357 } 332 358 333 359 static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, int *current_perm, ··· 734 690 735 691 qcom_q6v5_prepare(&qproc->q6v5); 736 692 693 + ret = q6v5_pds_enable(qproc, qproc->active_pds, qproc->active_pd_count); 694 + if (ret < 0) { 695 + dev_err(qproc->dev, "failed to enable active power domains\n"); 696 + goto disable_irqs; 697 + } 698 + 699 + ret = q6v5_pds_enable(qproc, qproc->proxy_pds, qproc->proxy_pd_count); 700 + if (ret < 0) { 701 + dev_err(qproc->dev, "failed to enable proxy power domains\n"); 702 + goto disable_active_pds; 703 + } 704 + 737 705 ret = q6v5_regulator_enable(qproc, qproc->proxy_regs, 738 706 qproc->proxy_reg_count); 739 707 if (ret) { 740 708 dev_err(qproc->dev, "failed to enable proxy supplies\n"); 741 - goto disable_irqs; 709 + goto disable_proxy_pds; 742 710 } 743 711 744 712 ret = q6v5_clk_enable(qproc->dev, qproc->proxy_clks, ··· 847 791 disable_proxy_reg: 848 792 q6v5_regulator_disable(qproc, qproc->proxy_regs, 849 793 qproc->proxy_reg_count); 794 + disable_proxy_pds: 795 + q6v5_pds_disable(qproc, qproc->proxy_pds, qproc->proxy_pd_count); 796 + disable_active_pds: 797 + q6v5_pds_disable(qproc, qproc->active_pds, qproc->active_pd_count); 850 798 disable_irqs: 851 799 qcom_q6v5_unprepare(&qproc->q6v5); 852 800 ··· 890 830 qproc->active_clk_count); 891 831 q6v5_regulator_disable(qproc, qproc->active_regs, 892 832 qproc->active_reg_count); 833 + q6v5_pds_disable(qproc, qproc->active_pds, qproc->active_pd_count); 893 834 894 835 /* In case of failure or coredump scenario where reclaiming MBA memory 895 836 * could not happen reclaim it here. ··· 902 841 903 842 ret = qcom_q6v5_unprepare(&qproc->q6v5); 904 843 if (ret) { 844 + q6v5_pds_disable(qproc, qproc->proxy_pds, 845 + qproc->proxy_pd_count); 905 846 q6v5_clk_disable(qproc->dev, qproc->proxy_clks, 906 847 qproc->proxy_clk_count); 907 848 q6v5_regulator_disable(qproc, qproc->proxy_regs, ··· 923 860 phys_addr_t min_addr = PHYS_ADDR_MAX; 924 861 phys_addr_t max_addr = 0; 925 862 bool relocate = false; 926 - char seg_name[10]; 863 + char *fw_name; 864 + size_t fw_name_len; 927 865 ssize_t offset; 928 866 size_t size = 0; 929 867 void *ptr; 930 868 int ret; 931 869 int i; 932 870 933 - ret = request_firmware(&fw, "modem.mdt", qproc->dev); 871 + fw_name_len = strlen(qproc->hexagon_mdt_image); 872 + if (fw_name_len <= 4) 873 + return -EINVAL; 874 + 875 + fw_name = kstrdup(qproc->hexagon_mdt_image, GFP_KERNEL); 876 + if (!fw_name) 877 + return -ENOMEM; 878 + 879 + ret = request_firmware(&fw, fw_name, qproc->dev); 934 880 if (ret < 0) { 935 - dev_err(qproc->dev, "unable to load modem.mdt\n"); 936 - return ret; 881 + dev_err(qproc->dev, "unable to load %s\n", fw_name); 882 + goto out; 937 883 } 938 884 939 885 /* Initialize the RMB validator */ ··· 990 918 ptr = qproc->mpss_region + offset; 991 919 992 920 if (phdr->p_filesz) { 993 - snprintf(seg_name, sizeof(seg_name), "modem.b%02d", i); 994 - ret = request_firmware(&seg_fw, seg_name, qproc->dev); 921 + /* Replace "xxx.xxx" with "xxx.bxx" */ 922 + sprintf(fw_name + fw_name_len - 3, "b%02d", i); 923 + ret = request_firmware(&seg_fw, fw_name, qproc->dev); 995 924 if (ret) { 996 - dev_err(qproc->dev, "failed to load %s\n", seg_name); 925 + dev_err(qproc->dev, "failed to load %s\n", fw_name); 997 926 goto release_firmware; 998 927 } 999 928 ··· 1033 960 1034 961 release_firmware: 1035 962 release_firmware(fw); 963 + out: 964 + kfree(fw_name); 1036 965 1037 966 return ret < 0 ? ret : 0; 1038 967 } ··· 1150 1075 unsigned long i; 1151 1076 int ret; 1152 1077 1153 - ret = request_firmware(&fw, "modem.mdt", qproc->dev); 1078 + ret = request_firmware(&fw, qproc->hexagon_mdt_image, qproc->dev); 1154 1079 if (ret < 0) { 1155 - dev_err(qproc->dev, "unable to load modem.mdt\n"); 1080 + dev_err(qproc->dev, "unable to load %s\n", 1081 + qproc->hexagon_mdt_image); 1156 1082 return ret; 1157 1083 } 1158 1084 ··· 1197 1121 qproc->proxy_clk_count); 1198 1122 q6v5_regulator_disable(qproc, qproc->proxy_regs, 1199 1123 qproc->proxy_reg_count); 1124 + q6v5_pds_disable(qproc, qproc->proxy_pds, qproc->proxy_pd_count); 1200 1125 } 1201 1126 1202 1127 static int q6v5_init_mem(struct q6v5 *qproc, struct platform_device *pdev) ··· 1256 1179 } 1257 1180 1258 1181 return i; 1182 + } 1183 + 1184 + static int q6v5_pds_attach(struct device *dev, struct device **devs, 1185 + char **pd_names) 1186 + { 1187 + size_t num_pds = 0; 1188 + int ret; 1189 + int i; 1190 + 1191 + if (!pd_names) 1192 + return 0; 1193 + 1194 + while (pd_names[num_pds]) 1195 + num_pds++; 1196 + 1197 + for (i = 0; i < num_pds; i++) { 1198 + devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]); 1199 + if (IS_ERR(devs[i])) { 1200 + ret = PTR_ERR(devs[i]); 1201 + goto unroll_attach; 1202 + } 1203 + } 1204 + 1205 + return num_pds; 1206 + 1207 + unroll_attach: 1208 + for (i--; i >= 0; i--) 1209 + dev_pm_domain_detach(devs[i], false); 1210 + 1211 + return ret; 1212 + }; 1213 + 1214 + static void q6v5_pds_detach(struct q6v5 *qproc, struct device **pds, 1215 + size_t pd_count) 1216 + { 1217 + int i; 1218 + 1219 + for (i = 0; i < pd_count; i++) 1220 + dev_pm_domain_detach(pds[i], false); 1259 1221 } 1260 1222 1261 1223 static int q6v5_init_reset(struct q6v5 *qproc) ··· 1369 1253 const struct rproc_hexagon_res *desc; 1370 1254 struct q6v5 *qproc; 1371 1255 struct rproc *rproc; 1256 + const char *mba_image; 1372 1257 int ret; 1373 1258 1374 1259 desc = of_device_get_match_data(&pdev->dev); ··· 1379 1262 if (desc->need_mem_protection && !qcom_scm_is_available()) 1380 1263 return -EPROBE_DEFER; 1381 1264 1265 + mba_image = desc->hexagon_mba_image; 1266 + ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name", 1267 + 0, &mba_image); 1268 + if (ret < 0 && ret != -EINVAL) 1269 + return ret; 1270 + 1382 1271 rproc = rproc_alloc(&pdev->dev, pdev->name, &q6v5_ops, 1383 - desc->hexagon_mba_image, sizeof(*qproc)); 1272 + mba_image, sizeof(*qproc)); 1384 1273 if (!rproc) { 1385 1274 dev_err(&pdev->dev, "failed to allocate rproc\n"); 1386 1275 return -ENOMEM; 1387 1276 } 1388 1277 1278 + rproc->auto_boot = false; 1279 + 1389 1280 qproc = (struct q6v5 *)rproc->priv; 1390 1281 qproc->dev = &pdev->dev; 1391 1282 qproc->rproc = rproc; 1283 + qproc->hexagon_mdt_image = "modem.mdt"; 1284 + ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name", 1285 + 1, &qproc->hexagon_mdt_image); 1286 + if (ret < 0 && ret != -EINVAL) 1287 + return ret; 1288 + 1392 1289 platform_set_drvdata(pdev, qproc); 1393 1290 1394 1291 ret = q6v5_init_mem(qproc, pdev); ··· 1453 1322 } 1454 1323 qproc->active_reg_count = ret; 1455 1324 1325 + ret = q6v5_pds_attach(&pdev->dev, qproc->active_pds, 1326 + desc->active_pd_names); 1327 + if (ret < 0) { 1328 + dev_err(&pdev->dev, "Failed to attach active power domains\n"); 1329 + goto free_rproc; 1330 + } 1331 + qproc->active_pd_count = ret; 1332 + 1333 + ret = q6v5_pds_attach(&pdev->dev, qproc->proxy_pds, 1334 + desc->proxy_pd_names); 1335 + if (ret < 0) { 1336 + dev_err(&pdev->dev, "Failed to init power domains\n"); 1337 + goto detach_active_pds; 1338 + } 1339 + qproc->proxy_pd_count = ret; 1340 + 1456 1341 qproc->has_alt_reset = desc->has_alt_reset; 1457 1342 ret = q6v5_init_reset(qproc); 1458 1343 if (ret) 1459 - goto free_rproc; 1344 + goto detach_proxy_pds; 1460 1345 1461 1346 qproc->version = desc->version; 1462 1347 qproc->need_mem_protection = desc->need_mem_protection; ··· 1480 1333 ret = qcom_q6v5_init(&qproc->q6v5, pdev, rproc, MPSS_CRASH_REASON_SMEM, 1481 1334 qcom_msa_handover); 1482 1335 if (ret) 1483 - goto free_rproc; 1336 + goto detach_proxy_pds; 1484 1337 1485 1338 qproc->mpss_perm = BIT(QCOM_SCM_VMID_HLOS); 1486 1339 qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS); ··· 1488 1341 qcom_add_smd_subdev(rproc, &qproc->smd_subdev); 1489 1342 qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss"); 1490 1343 qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12); 1344 + if (IS_ERR(qproc->sysmon)) { 1345 + ret = PTR_ERR(qproc->sysmon); 1346 + goto detach_proxy_pds; 1347 + } 1491 1348 1492 1349 ret = rproc_add(rproc); 1493 1350 if (ret) 1494 - goto free_rproc; 1351 + goto detach_proxy_pds; 1495 1352 1496 1353 return 0; 1497 1354 1355 + detach_proxy_pds: 1356 + q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count); 1357 + detach_active_pds: 1358 + q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count); 1498 1359 free_rproc: 1499 1360 rproc_free(rproc); 1500 1361 ··· 1519 1364 qcom_remove_glink_subdev(qproc->rproc, &qproc->glink_subdev); 1520 1365 qcom_remove_smd_subdev(qproc->rproc, &qproc->smd_subdev); 1521 1366 qcom_remove_ssr_subdev(qproc->rproc, &qproc->ssr_subdev); 1367 + 1368 + q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count); 1369 + q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count); 1370 + 1522 1371 rproc_free(qproc->rproc); 1523 1372 1524 1373 return 0; ··· 1547 1388 "mnoc_axi", 1548 1389 NULL 1549 1390 }, 1391 + .active_pd_names = (char*[]){ 1392 + "load_state", 1393 + NULL 1394 + }, 1395 + .proxy_pd_names = (char*[]){ 1396 + "cx", 1397 + "mx", 1398 + "mss", 1399 + NULL 1400 + }, 1550 1401 .need_mem_protection = true, 1551 1402 .has_alt_reset = true, 1552 1403 .version = MSS_SDM845, ··· 1564 1395 1565 1396 static const struct rproc_hexagon_res msm8996_mss = { 1566 1397 .hexagon_mba_image = "mba.mbn", 1398 + .proxy_supply = (struct qcom_mss_reg_res[]) { 1399 + { 1400 + .supply = "pll", 1401 + .uA = 100000, 1402 + }, 1403 + {} 1404 + }, 1567 1405 .proxy_clk_names = (char*[]){ 1568 1406 "xo", 1569 1407 "pnoc", 1408 + "qdss", 1570 1409 NULL 1571 1410 }, 1572 1411 .active_clk_names = (char*[]){ 1573 1412 "iface", 1574 1413 "bus", 1575 1414 "mem", 1576 - "gpll0_mss_clk", 1415 + "gpll0_mss", 1416 + "snoc_axi", 1417 + "mnoc_axi", 1577 1418 NULL 1578 1419 }, 1579 1420 .need_mem_protection = true,
+12 -1
drivers/remoteproc/qcom_q6v5_pas.c
··· 258 258 const struct adsp_data *desc; 259 259 struct qcom_adsp *adsp; 260 260 struct rproc *rproc; 261 + const char *fw_name; 261 262 int ret; 262 263 263 264 desc = of_device_get_match_data(&pdev->dev); ··· 268 267 if (!qcom_scm_is_available()) 269 268 return -EPROBE_DEFER; 270 269 270 + fw_name = desc->firmware_name; 271 + ret = of_property_read_string(pdev->dev.of_node, "firmware-name", 272 + &fw_name); 273 + if (ret < 0 && ret != -EINVAL) 274 + return ret; 275 + 271 276 rproc = rproc_alloc(&pdev->dev, pdev->name, &adsp_ops, 272 - desc->firmware_name, sizeof(*adsp)); 277 + fw_name, sizeof(*adsp)); 273 278 if (!rproc) { 274 279 dev_err(&pdev->dev, "unable to allocate remoteproc\n"); 275 280 return -ENOMEM; ··· 311 304 adsp->sysmon = qcom_add_sysmon_subdev(rproc, 312 305 desc->sysmon_name, 313 306 desc->ssctl_id); 307 + if (IS_ERR(adsp->sysmon)) { 308 + ret = PTR_ERR(adsp->sysmon); 309 + goto free_rproc; 310 + } 314 311 315 312 ret = rproc_add(rproc); 316 313 if (ret)
+78 -4
drivers/remoteproc/qcom_sysmon.c
··· 6 6 #include <linux/module.h> 7 7 #include <linux/notifier.h> 8 8 #include <linux/slab.h> 9 + #include <linux/interrupt.h> 9 10 #include <linux/io.h> 10 - #include <linux/notifier.h> 11 + #include <linux/of_irq.h> 11 12 #include <linux/of_platform.h> 12 13 #include <linux/platform_device.h> 13 14 #include <linux/remoteproc/qcom_rproc.h> ··· 26 25 27 26 const char *name; 28 27 28 + int shutdown_irq; 29 29 int ssctl_version; 30 30 int ssctl_instance; 31 31 ··· 36 34 37 35 struct rpmsg_endpoint *ept; 38 36 struct completion comp; 37 + struct completion ind_comp; 38 + struct completion shutdown_comp; 39 39 struct mutex lock; 40 40 41 41 bool ssr_ack; ··· 141 137 } 142 138 143 139 #define SSCTL_SHUTDOWN_REQ 0x21 140 + #define SSCTL_SHUTDOWN_READY_IND 0x21 144 141 #define SSCTL_SUBSYS_EVENT_REQ 0x23 145 142 146 143 #define SSCTL_MAX_MSG_LEN 7 ··· 257 252 {} 258 253 }; 259 254 255 + static struct qmi_elem_info ssctl_shutdown_ind_ei[] = { 256 + {} 257 + }; 258 + 259 + static void sysmon_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 260 + struct qmi_txn *txn, const void *data) 261 + { 262 + struct qcom_sysmon *sysmon = container_of(qmi, struct qcom_sysmon, qmi); 263 + 264 + complete(&sysmon->ind_comp); 265 + } 266 + 267 + static struct qmi_msg_handler qmi_indication_handler[] = { 268 + { 269 + .type = QMI_INDICATION, 270 + .msg_id = SSCTL_SHUTDOWN_READY_IND, 271 + .ei = ssctl_shutdown_ind_ei, 272 + .decoded_size = 0, 273 + .fn = sysmon_ind_cb 274 + }, 275 + {} 276 + }; 277 + 260 278 /** 261 279 * ssctl_request_shutdown() - request shutdown via SSCTL QMI service 262 280 * @sysmon: sysmon context ··· 290 262 struct qmi_txn txn; 291 263 int ret; 292 264 265 + reinit_completion(&sysmon->ind_comp); 266 + reinit_completion(&sysmon->shutdown_comp); 293 267 ret = qmi_txn_init(&sysmon->qmi, &txn, ssctl_shutdown_resp_ei, &resp); 294 268 if (ret < 0) { 295 269 dev_err(sysmon->dev, "failed to allocate QMI txn\n"); ··· 313 283 dev_err(sysmon->dev, "shutdown request failed\n"); 314 284 else 315 285 dev_dbg(sysmon->dev, "shutdown request completed\n"); 286 + 287 + if (sysmon->shutdown_irq > 0) { 288 + ret = wait_for_completion_timeout(&sysmon->shutdown_comp, 289 + 10 * HZ); 290 + if (!ret) { 291 + ret = try_wait_for_completion(&sysmon->ind_comp); 292 + if (!ret) 293 + dev_err(sysmon->dev, 294 + "timeout waiting for shutdown ack\n"); 295 + } 296 + } 316 297 } 317 298 318 299 /** ··· 473 432 return NOTIFY_DONE; 474 433 } 475 434 435 + static irqreturn_t sysmon_shutdown_interrupt(int irq, void *data) 436 + { 437 + struct qcom_sysmon *sysmon = data; 438 + 439 + complete(&sysmon->shutdown_comp); 440 + 441 + return IRQ_HANDLED; 442 + } 443 + 476 444 /** 477 445 * qcom_add_sysmon_subdev() - create a sysmon subdev for the given remoteproc 478 446 * @rproc: rproc context to associate the subdev with ··· 499 449 500 450 sysmon = kzalloc(sizeof(*sysmon), GFP_KERNEL); 501 451 if (!sysmon) 502 - return NULL; 452 + return ERR_PTR(-ENOMEM); 503 453 504 454 sysmon->dev = rproc->dev.parent; 505 455 sysmon->rproc = rproc; ··· 508 458 sysmon->ssctl_instance = ssctl_instance; 509 459 510 460 init_completion(&sysmon->comp); 461 + init_completion(&sysmon->ind_comp); 462 + init_completion(&sysmon->shutdown_comp); 511 463 mutex_init(&sysmon->lock); 512 464 513 - ret = qmi_handle_init(&sysmon->qmi, SSCTL_MAX_MSG_LEN, &ssctl_ops, NULL); 465 + sysmon->shutdown_irq = of_irq_get_byname(sysmon->dev->of_node, 466 + "shutdown-ack"); 467 + if (sysmon->shutdown_irq < 0) { 468 + if (sysmon->shutdown_irq != -ENODATA) { 469 + dev_err(sysmon->dev, 470 + "failed to retrieve shutdown-ack IRQ\n"); 471 + return ERR_PTR(sysmon->shutdown_irq); 472 + } 473 + } else { 474 + ret = devm_request_threaded_irq(sysmon->dev, 475 + sysmon->shutdown_irq, 476 + NULL, sysmon_shutdown_interrupt, 477 + IRQF_TRIGGER_RISING | IRQF_ONESHOT, 478 + "q6v5 shutdown-ack", sysmon); 479 + if (ret) { 480 + dev_err(sysmon->dev, 481 + "failed to acquire shutdown-ack IRQ\n"); 482 + return ERR_PTR(ret); 483 + } 484 + } 485 + 486 + ret = qmi_handle_init(&sysmon->qmi, SSCTL_MAX_MSG_LEN, &ssctl_ops, 487 + qmi_indication_handler); 514 488 if (ret < 0) { 515 489 dev_err(sysmon->dev, "failed to initialize qmi handle\n"); 516 490 kfree(sysmon); 517 - return NULL; 491 + return ERR_PTR(ret); 518 492 } 519 493 520 494 qmi_add_lookup(&sysmon->qmi, 43, 0, 0);
+5 -1
drivers/remoteproc/qcom_wcnss.c
··· 553 553 554 554 qcom_add_smd_subdev(rproc, &wcnss->smd_subdev); 555 555 wcnss->sysmon = qcom_add_sysmon_subdev(rproc, "wcnss", WCNSS_SSCTL_ID); 556 + if (IS_ERR(wcnss->sysmon)) { 557 + ret = PTR_ERR(wcnss->sysmon); 558 + goto free_rproc; 559 + } 556 560 557 561 ret = rproc_add(rproc); 558 562 if (ret) ··· 626 622 } 627 623 module_exit(wcnss_exit); 628 624 629 - MODULE_DESCRIPTION("Qualcomm Peripherial Image Loader for Wireless Subsystem"); 625 + MODULE_DESCRIPTION("Qualcomm Peripheral Image Loader for Wireless Subsystem"); 630 626 MODULE_LICENSE("GPL v2");
+112 -48
drivers/remoteproc/remoteproc_core.c
··· 39 39 #include <linux/idr.h> 40 40 #include <linux/elf.h> 41 41 #include <linux/crc32.h> 42 + #include <linux/of_reserved_mem.h> 42 43 #include <linux/virtio_ids.h> 43 44 #include <linux/virtio_ring.h> 44 45 #include <asm/byteorder.h> 46 + #include <linux/platform_device.h> 45 47 46 48 #include "remoteproc_internal.h" 49 + 50 + #define HIGH_BITS_MASK 0xFFFFFFFF00000000ULL 47 51 48 52 static DEFINE_MUTEX(rproc_list_mutex); 49 53 static LIST_HEAD(rproc_list); ··· 149 145 iommu_domain_free(domain); 150 146 } 151 147 152 - static phys_addr_t rproc_va_to_pa(void *cpu_addr) 148 + phys_addr_t rproc_va_to_pa(void *cpu_addr) 153 149 { 154 150 /* 155 151 * Return physical address according to virtual address location ··· 164 160 WARN_ON(!virt_addr_valid(cpu_addr)); 165 161 return virt_to_phys(cpu_addr); 166 162 } 163 + EXPORT_SYMBOL(rproc_va_to_pa); 167 164 168 165 /** 169 166 * rproc_da_to_va() - lookup the kernel virtual address for a remoteproc address ··· 208 203 209 204 list_for_each_entry(carveout, &rproc->carveouts, node) { 210 205 int offset = da - carveout->da; 206 + 207 + /* Verify that carveout is allocated */ 208 + if (!carveout->va) 209 + continue; 211 210 212 211 /* try next carveout if da is too small */ 213 212 if (offset < 0) ··· 281 272 * @len: associated area size 282 273 * 283 274 * This function is a helper function to verify requested device area (couple 284 - * da, len) is part of specified carevout. 275 + * da, len) is part of specified carveout. 276 + * If da is not set (defined as FW_RSC_ADDR_ANY), only requested length is 277 + * checked. 285 278 * 286 - * Return: 0 if carveout match request else -ENOMEM 279 + * Return: 0 if carveout matches request else error 287 280 */ 288 - int rproc_check_carveout_da(struct rproc *rproc, struct rproc_mem_entry *mem, 289 - u32 da, u32 len) 281 + static int rproc_check_carveout_da(struct rproc *rproc, 282 + struct rproc_mem_entry *mem, u32 da, u32 len) 290 283 { 291 284 struct device *dev = &rproc->dev; 292 - int delta = 0; 285 + int delta; 293 286 294 287 /* Check requested resource length */ 295 288 if (len > mem->len) { 296 289 dev_err(dev, "Registered carveout doesn't fit len request\n"); 297 - return -ENOMEM; 290 + return -EINVAL; 298 291 } 299 292 300 293 if (da != FW_RSC_ADDR_ANY && mem->da == FW_RSC_ADDR_ANY) { 301 - /* Update existing carveout da */ 302 - mem->da = da; 294 + /* Address doesn't match registered carveout configuration */ 295 + return -EINVAL; 303 296 } else if (da != FW_RSC_ADDR_ANY && mem->da != FW_RSC_ADDR_ANY) { 304 297 delta = da - mem->da; 305 298 ··· 309 298 if (delta < 0) { 310 299 dev_err(dev, 311 300 "Registered carveout doesn't fit da request\n"); 312 - return -ENOMEM; 301 + return -EINVAL; 313 302 } 314 303 315 304 if (delta + len > mem->len) { 316 305 dev_err(dev, 317 306 "Registered carveout doesn't fit len request\n"); 318 - return -ENOMEM; 307 + return -EINVAL; 319 308 } 320 309 } 321 310 ··· 429 418 static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed) 430 419 { 431 420 struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev); 421 + int ret; 432 422 433 - rproc_remove_virtio_dev(rvdev); 423 + ret = device_for_each_child(&rvdev->dev, NULL, rproc_remove_virtio_dev); 424 + if (ret) 425 + dev_warn(&rvdev->dev, "can't remove vdev child device: %d\n", ret); 426 + } 427 + 428 + /** 429 + * rproc_rvdev_release() - release the existence of a rvdev 430 + * 431 + * @dev: the subdevice's dev 432 + */ 433 + static void rproc_rvdev_release(struct device *dev) 434 + { 435 + struct rproc_vdev *rvdev = container_of(dev, struct rproc_vdev, dev); 436 + 437 + of_reserved_mem_device_release(dev); 438 + 439 + kfree(rvdev); 434 440 } 435 441 436 442 /** ··· 483 455 struct device *dev = &rproc->dev; 484 456 struct rproc_vdev *rvdev; 485 457 int i, ret; 458 + char name[16]; 486 459 487 460 /* make sure resource isn't truncated */ 488 461 if (sizeof(*rsc) + rsc->num_of_vrings * sizeof(struct fw_rsc_vdev_vring) ··· 517 488 rvdev->rproc = rproc; 518 489 rvdev->index = rproc->nb_vdev++; 519 490 491 + /* Initialise vdev subdevice */ 492 + snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index); 493 + rvdev->dev.parent = rproc->dev.parent; 494 + rvdev->dev.release = rproc_rvdev_release; 495 + dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name); 496 + dev_set_drvdata(&rvdev->dev, rvdev); 497 + 498 + ret = device_register(&rvdev->dev); 499 + if (ret) { 500 + put_device(&rvdev->dev); 501 + return ret; 502 + } 503 + /* Make device dma capable by inheriting from parent's capabilities */ 504 + set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent)); 505 + 506 + ret = dma_coerce_mask_and_coherent(&rvdev->dev, 507 + dma_get_mask(rproc->dev.parent)); 508 + if (ret) { 509 + dev_warn(dev, 510 + "Failed to set DMA mask %llx. Trying to continue... %x\n", 511 + dma_get_mask(rproc->dev.parent), ret); 512 + } 513 + 520 514 /* parse the vrings */ 521 515 for (i = 0; i < rsc->num_of_vrings; i++) { 522 516 ret = rproc_parse_vring(rvdev, rsc, i); ··· 570 518 for (i--; i >= 0; i--) 571 519 rproc_free_vring(&rvdev->vring[i]); 572 520 free_rvdev: 573 - kfree(rvdev); 521 + device_unregister(&rvdev->dev); 574 522 return ret; 575 523 } 576 524 ··· 588 536 589 537 rproc_remove_subdev(rproc, &rvdev->subdev); 590 538 list_del(&rvdev->node); 591 - kfree(rvdev); 539 + device_unregister(&rvdev->dev); 592 540 } 593 541 594 542 /** ··· 610 558 static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc, 611 559 int offset, int avail) 612 560 { 613 - struct rproc_mem_entry *trace; 561 + struct rproc_debug_trace *trace; 614 562 struct device *dev = &rproc->dev; 615 - void *ptr; 616 563 char name[15]; 617 564 618 565 if (sizeof(*rsc) > avail) { ··· 625 574 return -EINVAL; 626 575 } 627 576 628 - /* what's the kernel address of this resource ? */ 629 - ptr = rproc_da_to_va(rproc, rsc->da, rsc->len); 630 - if (!ptr) { 631 - dev_err(dev, "erroneous trace resource entry\n"); 632 - return -EINVAL; 633 - } 634 - 635 577 trace = kzalloc(sizeof(*trace), GFP_KERNEL); 636 578 if (!trace) 637 579 return -ENOMEM; 638 580 639 581 /* set the trace buffer dma properties */ 640 - trace->len = rsc->len; 641 - trace->va = ptr; 582 + trace->trace_mem.len = rsc->len; 583 + trace->trace_mem.da = rsc->da; 584 + 585 + /* set pointer on rproc device */ 586 + trace->rproc = rproc; 642 587 643 588 /* make sure snprintf always null terminates, even if truncating */ 644 589 snprintf(name, sizeof(name), "trace%d", rproc->num_traces); 645 590 646 591 /* create the debugfs entry */ 647 - trace->priv = rproc_create_trace_file(name, rproc, trace); 648 - if (!trace->priv) { 649 - trace->va = NULL; 592 + trace->tfile = rproc_create_trace_file(name, rproc, trace); 593 + if (!trace->tfile) { 650 594 kfree(trace); 651 595 return -EINVAL; 652 596 } ··· 650 604 651 605 rproc->num_traces++; 652 606 653 - dev_dbg(dev, "%s added: va %pK, da 0x%x, len 0x%x\n", 654 - name, ptr, rsc->da, rsc->len); 607 + dev_dbg(dev, "%s added: da 0x%x, len 0x%x\n", 608 + name, rsc->da, rsc->len); 655 609 656 610 return 0; 657 611 } ··· 761 715 dev_dbg(dev, "carveout va %pK, dma %pad, len 0x%x\n", 762 716 va, &dma, mem->len); 763 717 718 + if (mem->da != FW_RSC_ADDR_ANY && !rproc->domain) { 719 + /* 720 + * Check requested da is equal to dma address 721 + * and print a warn message in case of missalignment. 722 + * Don't stop rproc_start sequence as coprocessor may 723 + * build pa to da translation on its side. 724 + */ 725 + if (mem->da != (u32)dma) 726 + dev_warn(dev->parent, 727 + "Allocated carveout doesn't fit device address request\n"); 728 + } 729 + 764 730 /* 765 731 * Ok, this is non-standard. 766 732 * ··· 790 732 * to use the iommu-based DMA API: we expect 'dma' to contain the 791 733 * physical address in this case. 792 734 */ 793 - 794 - if (mem->da != FW_RSC_ADDR_ANY) { 795 - if (!rproc->domain) { 796 - dev_err(dev->parent, 797 - "Bad carveout rsc configuration\n"); 798 - ret = -ENOMEM; 799 - goto dma_free; 800 - } 801 - 735 + if (mem->da != FW_RSC_ADDR_ANY && rproc->domain) { 802 736 mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); 803 737 if (!mapping) { 804 738 ret = -ENOMEM; ··· 817 767 818 768 dev_dbg(dev, "carveout mapped 0x%x to %pad\n", 819 769 mem->da, &dma); 820 - } else { 770 + } 771 + 772 + if (mem->da == FW_RSC_ADDR_ANY) { 773 + /* Update device address as undefined by requester */ 774 + if ((u64)dma & HIGH_BITS_MASK) 775 + dev_warn(dev, "DMA address cast in 32bit to fit resource table format\n"); 776 + 821 777 mem->da = (u32)dma; 822 778 } 823 779 824 - mem->dma = (u32)dma; 780 + mem->dma = dma; 825 781 mem->va = va; 826 782 827 783 return 0; ··· 956 900 * @dma: dma address 957 901 * @len: memory carveout length 958 902 * @da: device address 959 - * @release: memory carveout function 903 + * @alloc: memory carveout allocation function 904 + * @release: memory carveout release function 960 905 * @name: carveout name 961 906 * 962 907 * This function allocates a rproc_mem_entry struct and fill it with parameters ··· 1167 1110 struct rproc_mem_entry *entry, *tmp; 1168 1111 struct fw_rsc_carveout *rsc; 1169 1112 struct device *dev = &rproc->dev; 1113 + u64 pa; 1170 1114 int ret; 1171 1115 1172 1116 list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) { ··· 1204 1146 1205 1147 /* Use va if defined else dma to generate pa */ 1206 1148 if (entry->va) 1207 - rsc->pa = (u32)rproc_va_to_pa(entry->va); 1149 + pa = (u64)rproc_va_to_pa(entry->va); 1208 1150 else 1209 - rsc->pa = (u32)entry->dma; 1151 + pa = (u64)entry->dma; 1210 1152 1153 + if (((u64)pa) & HIGH_BITS_MASK) 1154 + dev_warn(dev, 1155 + "Physical address cast in 32bit to fit resource table format\n"); 1156 + 1157 + rsc->pa = (u32)pa; 1211 1158 rsc->da = entry->da; 1212 1159 rsc->len = entry->len; 1213 1160 } ··· 1245 1182 static void rproc_resource_cleanup(struct rproc *rproc) 1246 1183 { 1247 1184 struct rproc_mem_entry *entry, *tmp; 1185 + struct rproc_debug_trace *trace, *ttmp; 1248 1186 struct rproc_vdev *rvdev, *rvtmp; 1249 1187 struct device *dev = &rproc->dev; 1250 1188 1251 1189 /* clean up debugfs trace entries */ 1252 - list_for_each_entry_safe(entry, tmp, &rproc->traces, node) { 1253 - rproc_remove_trace_file(entry->priv); 1190 + list_for_each_entry_safe(trace, ttmp, &rproc->traces, node) { 1191 + rproc_remove_trace_file(trace->tfile); 1254 1192 rproc->num_traces--; 1255 - list_del(&entry->node); 1256 - kfree(entry); 1193 + list_del(&trace->node); 1194 + kfree(trace); 1257 1195 } 1258 1196 1259 1197 /* clean up iommu mapping entries */
+43 -4
drivers/remoteproc/remoteproc_debugfs.c
··· 47 47 static ssize_t rproc_trace_read(struct file *filp, char __user *userbuf, 48 48 size_t count, loff_t *ppos) 49 49 { 50 - struct rproc_mem_entry *trace = filp->private_data; 51 - int len = strnlen(trace->va, trace->len); 50 + struct rproc_debug_trace *data = filp->private_data; 51 + struct rproc_mem_entry *trace = &data->trace_mem; 52 + void *va; 53 + char buf[100]; 54 + int len; 52 55 53 - return simple_read_from_buffer(userbuf, count, ppos, trace->va, len); 56 + va = rproc_da_to_va(data->rproc, trace->da, trace->len); 57 + 58 + if (!va) { 59 + len = scnprintf(buf, sizeof(buf), "Trace %s not available\n", 60 + trace->name); 61 + va = buf; 62 + } else { 63 + len = strnlen(va, trace->len); 64 + } 65 + 66 + return simple_read_from_buffer(userbuf, count, ppos, va, len); 54 67 } 55 68 56 69 static const struct file_operations trace_rproc_ops = { ··· 164 151 static const struct file_operations rproc_recovery_ops = { 165 152 .read = rproc_recovery_read, 166 153 .write = rproc_recovery_write, 154 + .open = simple_open, 155 + .llseek = generic_file_llseek, 156 + }; 157 + 158 + /* expose the crash trigger via debugfs */ 159 + static ssize_t 160 + rproc_crash_write(struct file *filp, const char __user *user_buf, 161 + size_t count, loff_t *ppos) 162 + { 163 + struct rproc *rproc = filp->private_data; 164 + unsigned int type; 165 + int ret; 166 + 167 + ret = kstrtouint_from_user(user_buf, count, 0, &type); 168 + if (ret < 0) 169 + return ret; 170 + 171 + rproc_report_crash(rproc, type); 172 + 173 + return count; 174 + } 175 + 176 + static const struct file_operations rproc_crash_ops = { 177 + .write = rproc_crash_write, 167 178 .open = simple_open, 168 179 .llseek = generic_file_llseek, 169 180 }; ··· 325 288 } 326 289 327 290 struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc, 328 - struct rproc_mem_entry *trace) 291 + struct rproc_debug_trace *trace) 329 292 { 330 293 struct dentry *tfile; 331 294 ··· 362 325 rproc, &rproc_name_ops); 363 326 debugfs_create_file("recovery", 0400, rproc->dbg_dir, 364 327 rproc, &rproc_recovery_ops); 328 + debugfs_create_file("crash", 0200, rproc->dbg_dir, 329 + rproc, &rproc_crash_ops); 365 330 debugfs_create_file("resource_table", 0400, rproc->dbg_dir, 366 331 rproc, &rproc_rsc_table_ops); 367 332 debugfs_create_file("carveout_memories", 0400, rproc->dbg_dir,
+10 -2
drivers/remoteproc/remoteproc_internal.h
··· 25 25 26 26 struct rproc; 27 27 28 + struct rproc_debug_trace { 29 + struct rproc *rproc; 30 + struct dentry *tfile; 31 + struct list_head node; 32 + struct rproc_mem_entry trace_mem; 33 + }; 34 + 28 35 /* from remoteproc_core.c */ 29 36 void rproc_release(struct kref *kref); 30 37 irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id); ··· 39 32 40 33 /* from remoteproc_virtio.c */ 41 34 int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id); 42 - void rproc_remove_virtio_dev(struct rproc_vdev *rvdev); 35 + int rproc_remove_virtio_dev(struct device *dev, void *data); 43 36 44 37 /* from remoteproc_debugfs.c */ 45 38 void rproc_remove_trace_file(struct dentry *tfile); 46 39 struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc, 47 - struct rproc_mem_entry *trace); 40 + struct rproc_debug_trace *trace); 48 41 void rproc_delete_debug_dir(struct rproc *rproc); 49 42 void rproc_create_debug_dir(struct rproc *rproc); 50 43 void rproc_init_debugfs(void); ··· 59 52 int rproc_alloc_vring(struct rproc_vdev *rvdev, int i); 60 53 61 54 void *rproc_da_to_va(struct rproc *rproc, u64 da, int len); 55 + phys_addr_t rproc_va_to_pa(void *cpu_addr); 62 56 int rproc_trigger_recovery(struct rproc *rproc); 63 57 64 58 int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw);
+56 -5
drivers/remoteproc/remoteproc_virtio.c
··· 17 17 * GNU General Public License for more details. 18 18 */ 19 19 20 + #include <linux/dma-mapping.h> 20 21 #include <linux/export.h> 22 + #include <linux/of_reserved_mem.h> 21 23 #include <linux/remoteproc.h> 22 24 #include <linux/virtio.h> 23 25 #include <linux/virtio_config.h> ··· 318 316 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 319 317 struct rproc *rproc = vdev_to_rproc(vdev); 320 318 319 + kfree(vdev); 320 + 321 321 kref_put(&rvdev->refcount, rproc_vdev_release); 322 322 323 323 put_device(&rproc->dev); ··· 337 333 int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) 338 334 { 339 335 struct rproc *rproc = rvdev->rproc; 340 - struct device *dev = &rproc->dev; 341 - struct virtio_device *vdev = &rvdev->vdev; 336 + struct device *dev = &rvdev->dev; 337 + struct virtio_device *vdev; 338 + struct rproc_mem_entry *mem; 342 339 int ret; 343 340 341 + /* Try to find dedicated vdev buffer carveout */ 342 + mem = rproc_find_carveout_by_name(rproc, "vdev%dbuffer", rvdev->index); 343 + if (mem) { 344 + phys_addr_t pa; 345 + 346 + if (mem->of_resm_idx != -1) { 347 + struct device_node *np = rproc->dev.parent->of_node; 348 + 349 + /* Associate reserved memory to vdev device */ 350 + ret = of_reserved_mem_device_init_by_idx(dev, np, 351 + mem->of_resm_idx); 352 + if (ret) { 353 + dev_err(dev, "Can't associate reserved memory\n"); 354 + goto out; 355 + } 356 + } else { 357 + if (mem->va) { 358 + dev_warn(dev, "vdev %d buffer already mapped\n", 359 + rvdev->index); 360 + pa = rproc_va_to_pa(mem->va); 361 + } else { 362 + /* Use dma address as carveout no memmapped yet */ 363 + pa = (phys_addr_t)mem->dma; 364 + } 365 + 366 + /* Associate vdev buffer memory pool to vdev subdev */ 367 + ret = dma_declare_coherent_memory(dev, pa, 368 + mem->da, 369 + mem->len); 370 + if (ret < 0) { 371 + dev_err(dev, "Failed to associate buffer\n"); 372 + goto out; 373 + } 374 + } 375 + } 376 + 377 + /* Allocate virtio device */ 378 + vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); 379 + if (!vdev) { 380 + ret = -ENOMEM; 381 + goto out; 382 + } 344 383 vdev->id.device = id, 345 384 vdev->config = &rproc_virtio_config_ops, 346 385 vdev->dev.parent = dev; ··· 417 370 418 371 /** 419 372 * rproc_remove_virtio_dev() - remove an rproc-induced virtio device 420 - * @rvdev: the remote vdev 373 + * @dev: the virtio device 374 + * @data: must be null 421 375 * 422 376 * This function unregisters an existing virtio device. 423 377 */ 424 - void rproc_remove_virtio_dev(struct rproc_vdev *rvdev) 378 + int rproc_remove_virtio_dev(struct device *dev, void *data) 425 379 { 426 - unregister_virtio_device(&rvdev->vdev); 380 + struct virtio_device *vdev = dev_to_virtio(dev); 381 + 382 + unregister_virtio_device(vdev); 383 + return 0; 427 384 }
+80 -11
drivers/remoteproc/st_remoteproc.c
··· 19 19 #include <linux/mfd/syscon.h> 20 20 #include <linux/module.h> 21 21 #include <linux/of.h> 22 + #include <linux/of_address.h> 22 23 #include <linux/of_device.h> 23 24 #include <linux/of_reserved_mem.h> 24 25 #include <linux/platform_device.h> ··· 92 91 dev_err(dev, "failed to send message via mbox: %d\n", ret); 93 92 } 94 93 94 + static int st_rproc_mem_alloc(struct rproc *rproc, 95 + struct rproc_mem_entry *mem) 96 + { 97 + struct device *dev = rproc->dev.parent; 98 + void *va; 99 + 100 + va = ioremap_wc(mem->dma, mem->len); 101 + if (!va) { 102 + dev_err(dev, "Unable to map memory region: %pa+%zx\n", 103 + &mem->dma, mem->len); 104 + return -ENOMEM; 105 + } 106 + 107 + /* Update memory entry va */ 108 + mem->va = va; 109 + 110 + return 0; 111 + } 112 + 113 + static int st_rproc_mem_release(struct rproc *rproc, 114 + struct rproc_mem_entry *mem) 115 + { 116 + iounmap(mem->va); 117 + 118 + return 0; 119 + } 120 + 121 + static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) 122 + { 123 + struct device *dev = rproc->dev.parent; 124 + struct device_node *np = dev->of_node; 125 + struct rproc_mem_entry *mem; 126 + struct reserved_mem *rmem; 127 + struct of_phandle_iterator it; 128 + int index = 0; 129 + 130 + of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); 131 + while (of_phandle_iterator_next(&it) == 0) { 132 + rmem = of_reserved_mem_lookup(it.node); 133 + if (!rmem) { 134 + dev_err(dev, "unable to acquire memory-region\n"); 135 + return -EINVAL; 136 + } 137 + 138 + /* No need to map vdev buffer */ 139 + if (strcmp(it.node->name, "vdev0buffer")) { 140 + /* Register memory region */ 141 + mem = rproc_mem_entry_init(dev, NULL, 142 + (dma_addr_t)rmem->base, 143 + rmem->size, rmem->base, 144 + st_rproc_mem_alloc, 145 + st_rproc_mem_release, 146 + it.node->name); 147 + } else { 148 + /* Register reserved memory for vdev buffer allocation */ 149 + mem = rproc_of_resm_mem_entry_init(dev, index, 150 + rmem->size, 151 + rmem->base, 152 + it.node->name); 153 + } 154 + 155 + if (!mem) 156 + return -ENOMEM; 157 + 158 + rproc_add_carveout(rproc, mem); 159 + index++; 160 + } 161 + 162 + return rproc_elf_load_rsc_table(rproc, fw); 163 + } 164 + 95 165 static int st_rproc_start(struct rproc *rproc) 96 166 { 97 167 struct st_rproc *ddata = rproc->priv; ··· 230 158 } 231 159 232 160 static const struct rproc_ops st_rproc_ops = { 233 - .kick = st_rproc_kick, 234 - .start = st_rproc_start, 235 - .stop = st_rproc_stop, 161 + .kick = st_rproc_kick, 162 + .start = st_rproc_start, 163 + .stop = st_rproc_stop, 164 + .parse_fw = st_rproc_parse_fw, 165 + .load = rproc_elf_load_segments, 166 + .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table, 167 + .sanity_check = rproc_elf_sanity_check, 168 + .get_boot_addr = rproc_elf_get_boot_addr, 236 169 }; 237 170 238 171 /* ··· 329 252 if (err) { 330 253 dev_err(dev, "Boot offset not found\n"); 331 254 return -EINVAL; 332 - } 333 - 334 - err = of_reserved_mem_device_init(dev); 335 - if (err) { 336 - dev_err(dev, "Failed to obtain shared memory\n"); 337 - return err; 338 255 } 339 256 340 257 err = clk_prepare(ddata->clk); ··· 457 386 rproc_del(rproc); 458 387 459 388 clk_disable_unprepare(ddata->clk); 460 - 461 - of_reserved_mem_device_release(&pdev->dev); 462 389 463 390 for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++) 464 391 mbox_free_channel(ddata->mbox_chan[i]);
+12 -12
drivers/rpmsg/virtio_rpmsg_bus.c
··· 11 11 12 12 #define pr_fmt(fmt) "%s: " fmt, __func__ 13 13 14 + #include <linux/dma-mapping.h> 15 + #include <linux/idr.h> 16 + #include <linux/jiffies.h> 14 17 #include <linux/kernel.h> 15 18 #include <linux/module.h> 19 + #include <linux/mutex.h> 20 + #include <linux/of_device.h> 21 + #include <linux/rpmsg.h> 22 + #include <linux/scatterlist.h> 23 + #include <linux/slab.h> 24 + #include <linux/sched.h> 16 25 #include <linux/virtio.h> 17 26 #include <linux/virtio_ids.h> 18 27 #include <linux/virtio_config.h> 19 - #include <linux/scatterlist.h> 20 - #include <linux/dma-mapping.h> 21 - #include <linux/slab.h> 22 - #include <linux/idr.h> 23 - #include <linux/jiffies.h> 24 - #include <linux/sched.h> 25 28 #include <linux/wait.h> 26 - #include <linux/rpmsg.h> 27 - #include <linux/mutex.h> 28 - #include <linux/of_device.h> 29 29 30 30 #include "rpmsg_internal.h" 31 31 ··· 912 912 total_buf_space = vrp->num_bufs * vrp->buf_size; 913 913 914 914 /* allocate coherent memory for the buffers */ 915 - bufs_va = dma_alloc_coherent(vdev->dev.parent->parent, 915 + bufs_va = dma_alloc_coherent(vdev->dev.parent, 916 916 total_buf_space, &vrp->bufs_dma, 917 917 GFP_KERNEL); 918 918 if (!bufs_va) { ··· 980 980 return 0; 981 981 982 982 free_coherent: 983 - dma_free_coherent(vdev->dev.parent->parent, total_buf_space, 983 + dma_free_coherent(vdev->dev.parent, total_buf_space, 984 984 bufs_va, vrp->bufs_dma); 985 985 vqs_del: 986 986 vdev->config->del_vqs(vrp->vdev); ··· 1015 1015 1016 1016 vdev->config->del_vqs(vrp->vdev); 1017 1017 1018 - dma_free_coherent(vdev->dev.parent->parent, total_buf_space, 1018 + dma_free_coherent(vdev->dev.parent, total_buf_space, 1019 1019 vrp->rbufs, vrp->bufs_dma); 1020 1020 1021 1021 kfree(vrp);
+4 -4
include/linux/remoteproc.h
··· 345 345 * @stop: power off the device 346 346 * @kick: kick a virtqueue (virtqueue id given as a parameter) 347 347 * @da_to_va: optional platform hook to perform address translations 348 - * @load_rsc_table: load resource table from firmware image 348 + * @parse_fw: parse firmware to extract information (e.g. resource table) 349 349 * @find_loaded_rsc_table: find the loaded resouce table 350 - * @load: load firmeware to memory, where the remote processor 350 + * @load: load firmware to memory, where the remote processor 351 351 * expects to find it 352 352 * @sanity_check: sanity check the fw image 353 353 * @get_boot_addr: get boot address to entry point specified in firmware ··· 554 554 struct kref refcount; 555 555 556 556 struct rproc_subdev subdev; 557 + struct device dev; 557 558 558 559 unsigned int id; 559 560 struct list_head node; 560 561 struct rproc *rproc; 561 - struct virtio_device vdev; 562 562 struct rproc_vring vring[RVDEV_NUM_VRINGS]; 563 563 u32 rsc_offset; 564 564 u32 index; ··· 601 601 602 602 static inline struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev) 603 603 { 604 - return container_of(vdev, struct rproc_vdev, vdev); 604 + return container_of(vdev->dev.parent, struct rproc_vdev, dev); 605 605 } 606 606 607 607 static inline struct rproc *vdev_to_rproc(struct virtio_device *vdev)