History

Merge tag 'rproc-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux

Pull remoteproc updates from Bjorn Andersson: - Add i.MX94 support to the i.MX remoteproc driver, covering the Cortex-M7 and Cortex-M33 Sync cores. This also fixes programming of non-zero System Manager CPU/LMM reset vectors. - Move the remoteproc resource table definitions to a separate header, so they can be used by clients that do not otherwise depend on remoteproc. Switch the firmware resource handling over to the common iterator. - Update the Xilinx R5F remoteproc driver to check the remote core state before attaching, drop a binding header dependency, and add firmware-name based auto boot support. - Add Qualcomm Hawi ADSP/CDSP bindings, together with Shikra RPM bindings and CDSP, LPAICP, and MPSS PAS support. Fix a Qualcomm minidump leak, clean up PAS and WCSS reset handling, and make the user-visible Qualcomm naming consistent. - Remove a duplicate STM32_RPROC Kconfig dependency and make i.MX remoteproc instances use the device node name so multiple processors can be distinguished in sysfs. * tag 'rproc-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux: remoteproc: qcom: pas: Drop start/stop completion from struct qcom_pas remoteproc: qcom: pas: Add Shikra remoteproc support dt-bindings: remoteproc: qcom,shikra-pas: Document Shikra PAS remoteprocs dt-bindings: remoteproc: Add Shikra RPM processor compatible remoteproc: qcom: Unify user-visible "Qualcomm" name remoteproc: qcom: Fix leak when custom dump_segments addition fails remoteproc: qcom_q6v5_wcss: drop redundant wcss_q6_bcr_reset dt-bindings: remoteproc: qcom,sm8550-pas: Add Hawi CDSP compatible dt-bindings: remoteproc: qcom,sm8550-pas: Add Hawi ADSP compatible remoteproc: xlnx: Enable auto boot feature dt-bindings: remoteproc: xlnx: Add firmware-name property remoteproc: xlnx: Remove binding header dependency remoteproc: imx_rproc: Use device node name as processor name remoteproc: use rsc_table_for_each_entry() in rproc_handle_resources() remoteproc: Move resource table data structure to its own header remoteproc: xlnx: Check remote core state remoteproc: imx_rproc: Add support for i.MX94 remoteproc: imx_rproc: Program non-zero SM CPU/LMM reset vector dt-bindings: remoteproc: imx-rproc: Support i.MX94 remoteproc: Dead code cleanup in Kconfig for STM32_RPROC

Linus Torvalds committed 4 months ago

Commit 9d0d4d12 parents 390d73a b5bfc7d17 files · +858 −367Browse files

Unified · Split

17 files
  1. Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml +3 −0
  2. Documentation/devicetree/bindings/remoteproc/qcom,rpm-proc.yaml +1 −0
  3. Documentation/devicetree/bindings/remoteproc/qcom,shikra-pas.yaml +167 −0
  4. Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml +4 −0
  5. Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml +4 −0
  6. drivers/firmware/xilinx/zynqmp.c +28 −0
  7. drivers/remoteproc/Kconfig +1 −2
  8. drivers/remoteproc/imx_rproc.c +91 −4
  9. drivers/remoteproc/imx_rproc.h +2 −0
  10. drivers/remoteproc/qcom_common.c +10 −4
  11. drivers/remoteproc/qcom_q6v5_pas.c +48 −3
  12. drivers/remoteproc/qcom_q6v5_wcss.c +5 −18
  13. drivers/remoteproc/remoteproc_core.c +38 −43
  14. drivers/remoteproc/xlnx_r5_remoteproc.c +75 −25
  15. include/linux/firmware/xlnx-zynqmp.h +21 −0
  16. include/linux/remoteproc.h +1 −268
  17. include/linux/rsc_table.h +359 −0
Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml+3−0
@@ -28,6 +28,9 @@ properties: · 27 unmodified lines
2828 - fsl,imx8qxp-cm4
2929 - fsl,imx8ulp-cm33
3030 - fsl,imx93-cm33
31+ - fsl,imx94-cm33s
32+ - fsl,imx94-cm70
33+ - fsl,imx94-cm71
3134 - fsl,imx95-cm7
3235
3336 clocks:
Documentation/devicetree/bindings/remoteproc/qcom,rpm-proc.yaml+1−0
@@ -87,6 +87,7 @@ properties: · 86 unmodified lines
8787 - qcom,qcm2290-rpm-proc
8888 - qcom,qcs404-rpm-proc
8989 - qcom,sdm660-rpm-proc
90+ - qcom,shikra-rpm-proc
9091 - qcom,sm6115-rpm-proc
9192 - qcom,sm6125-rpm-proc
9293 - qcom,sm6375-rpm-proc
Documentation/devicetree/bindings/remoteproc/qcom,shikra-pas.yaml+167−0
@@ -0,0 +1,167 @@
1+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
2+%YAML 1.2
3+---
4+$id: http://devicetree.org/schemas/remoteproc/qcom,shikra-pas.yaml#
5+$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+title: Qualcomm Shikra SoC Peripheral Authentication Service
8+
9+maintainers:
10+ - Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
11+ - Komal Bajaj <komal.bajaj@oss.qualcomm.com>
12+
13+description:
14+ Qualcomm Shikra SoC Peripheral Authentication Service loads and boots
15+ firmware on the Qualcomm DSP Hexagon cores.
16+
17+properties:
18+ compatible:
19+ enum:
20+ - qcom,shikra-cdsp-pas
21+ - qcom,shikra-lpaicp-pas
22+ - qcom,shikra-mpss-pas
23+
24+ reg:
25+ maxItems: 1
26+
27+ clocks:
28+ items:
29+ - description: XO clock
30+
31+ clock-names:
32+ items:
33+ - const: xo
34+
35+ memory-region:
36+ minItems: 1
37+ maxItems: 2
38+
39+ smd-edge: false
40+
41+ firmware-name:
42+ minItems: 1
43+ items:
44+ - description: Firmware name of the Hexagon core
45+ - description: Firmware name of the Hexagon Devicetree
46+
47+ glink-edge:
48+ $ref: /schemas/remoteproc/qcom,glink-edge.yaml#
49+ description:
50+ Qualcomm G-Link subnode which represents communication edge, channels
51+ and devices related to the remoteproc core.
52+ unevaluatedProperties: false
53+
54+ qcom,smem-states:
55+ $ref: /schemas/types.yaml#/definitions/phandle-array
56+ description: States used by the AP to signal the Hexagon core
57+ items:
58+ - description: Stop the remote processor
59+ items:
60+ - description: Phandle to the Shared Memory Point 2 Point device
61+ handling the communication with a remote processor
62+ - description: Single bit index to toggle in the value sent to
63+ the remote processor
64+ maximum: 32
65+
66+ qcom,smem-state-names:
67+ description: The names of the state bits used for SMP2P output
68+ items:
69+ - const: stop
70+
71+required:
72+ - compatible
73+ - reg
74+ - memory-region
75+
76+allOf:
77+ - $ref: /schemas/remoteproc/qcom,pas-common.yaml#
78+
79+ - if:
80+ properties:
81+ compatible:
82+ enum:
83+ - qcom,shikra-cdsp-pas
84+ - qcom,shikra-mpss-pas
85+ then:
86+ properties:
87+ interrupts:
88+ minItems: 6
89+ interrupt-names:
90+ minItems: 6
91+ memory-region:
92+ maxItems: 1
93+ firmware-name:
94+ maxItems: 1
95+ power-domains:
96+ items:
97+ - description: CX power domain
98+ power-domain-names:
99+ items:
100+ - const: cx
101+
102+ - if:
103+ properties:
104+ compatible:
105+ enum:
106+ - qcom,shikra-lpaicp-pas
107+ then:
108+ properties:
109+ interrupts:
110+ maxItems: 5
111+ interrupt-names:
112+ maxItems: 5
113+ memory-region:
114+ minItems: 2
115+ firmware-name:
116+ minItems: 2
117+ power-domains: false
118+ power-domain-names: false
119+
120+unevaluatedProperties: false
121+
122+examples:
123+ - |
124+ #include <dt-bindings/clock/qcom,rpmcc.h>
125+ #include <dt-bindings/interconnect/qcom,icc.h>
126+ #include <dt-bindings/interconnect/qcom,rpm-icc.h>
127+ #include <dt-bindings/interconnect/qcom,shikra.h>
128+ #include <dt-bindings/interrupt-controller/arm-gic.h>
129+ #include <dt-bindings/interrupt-controller/irq.h>
130+ #include <dt-bindings/power/qcom-rpmpd.h>
131+
132+ remoteproc@b300000 {
133+ compatible = "qcom,shikra-cdsp-pas";
134+ reg = <0x0b300000 0x100000>;
135+
136+ interrupts-extended = <&intc GIC_SPI 265 IRQ_TYPE_EDGE_RISING>,
137+ <&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
138+ <&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
139+ <&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
140+ <&cdsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>,
141+ <&cdsp_smp2p_in 7 IRQ_TYPE_EDGE_RISING>;
142+ interrupt-names = "wdog", "fatal", "ready",
143+ "handover", "stop-ack", "shutdown-ack";
144+
145+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>;
146+ clock-names = "xo";
147+
148+ interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG
149+ &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>;
150+
151+ power-domains = <&rpmpd RPMHPD_CX>;
152+ power-domain-names = "cx";
153+
154+ memory-region = <&cdsp_mem>;
155+
156+ qcom,smem-states = <&cdsp_smp2p_out 0>;
157+ qcom,smem-state-names = "stop";
158+
159+ firmware-name = "qcom/shikra/cdsp.mbn";
160+
161+ glink-edge {
162+ interrupts = <GIC_SPI 261 IRQ_TYPE_EDGE_RISING>;
163+ mboxes = <&apcs_glb 4>;
164+ qcom,remote-pid = <5>;
165+ label = "cdsp";
166+ };
167+ };
Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml+4−0
@@ -30,12 +30,14 @@ properties: · 29 unmodified lines
3030 - items:
3131 - enum:
3232 - qcom,glymur-adsp-pas
33+ - qcom,hawi-adsp-pas
3334 - qcom,kaanapali-adsp-pas
3435 - qcom,sm8750-adsp-pas
3536 - const: qcom,sm8550-adsp-pas
3637 - items:
3738 - enum:
3839 - qcom,glymur-cdsp-pas
40+ - qcom,hawi-cdsp-pas
3941 - qcom,kaanapali-cdsp-pas
4042 - const: qcom,sm8550-cdsp-pas
4143 - items:
@@ -104,6 +106,8 @@ allOf: · 62 unmodified lines
104106 enum:
105107 - qcom,glymur-adsp-pas
106108 - qcom,glymur-cdsp-pas
109+ - qcom,hawi-adsp-pas
110+ - qcom,hawi-cdsp-pas
107111 - qcom,kaanapali-adsp-pas
108112 - qcom,kaanapali-cdsp-pas
109113 - qcom,sm8750-adsp-pas
Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml+4−0
@@ -128,6 +128,10 @@ patternProperties: · 127 unmodified lines
128128 - description: vring1
129129 additionalItems: true
130130
131+ firmware-name:
132+ maxItems: 1
133+ description: default firmware to load
134+
131135 required:
132136 - compatible
133137 - reg
drivers/firmware/xilinx/zynqmp.c+28−0
@@ -1450,6 +1450,34 @@ int zynqmp_pm_get_node_status(const u32 node, u32 *const status, · 1449 unmodified lines
14501450 }
14511451 EXPORT_SYMBOL_GPL(zynqmp_pm_get_node_status);
14521452
1453+/**
1454+ * zynqmp_pm_get_rpu_node_status - PM call to request a RPU node's current power state
1455+ * @node: ID of the RPU component or sub-system in question
1456+ * @status: Current operating state of the requested RPU node.
1457+ * @requirements: Current requirements asserted on the RPU node.
1458+ * @usage: Usage information, used for RPU slave nodes only:
1459+ * PM_USAGE_NO_MASTER - No master is currently using
1460+ * the node
1461+ * PM_USAGE_CURRENT_MASTER - Only requesting master is
1462+ * currently using the node
1463+ * PM_USAGE_OTHER_MASTER - Only other masters are
1464+ * currently using the node
1465+ * PM_USAGE_BOTH_MASTERS - Both the current and at least
1466+ * one other master is currently
1467+ * using the node
1468+ *
1469+ * Return: Returns status, either success or error+reason
1470+ */
1471+int zynqmp_pm_get_rpu_node_status(const u32 node, u32 *const status,
1472+ u32 *const requirements, u32 *const usage)
1473+{
1474+ if (zynqmp_pm_feature(PM_GET_NODE_STATUS) < PM_API_VERSION_2)
1475+ return -EOPNOTSUPP;
1476+
1477+ return zynqmp_pm_get_node_status(node, status, requirements, usage);
1478+}
1479+EXPORT_SYMBOL_GPL(zynqmp_pm_get_rpu_node_status);
1480+
14531481 /**
14541482 * zynqmp_pm_force_pwrdwn - PM call to request for another PU or subsystem to
14551483 * be powered down forcefully
drivers/remoteproc/Kconfig+1−2
@@ -176,7 +176,7 @@ config QCOM_Q6V5_COMMON · 175 unmodified lines
176176 depends on QCOM_SMEM
177177
178178 config QCOM_Q6V5_ADSP
179− tristate "Qualcomm Technology Inc ADSP Peripheral Image Loader"
179+ tristate "Qualcomm ADSP Peripheral Image Loader"
180180 depends on OF && ARCH_QCOM
181181 depends on QCOM_SMEM
182182 depends on RPMSG_QCOM_SMD || RPMSG_QCOM_SMD=n
@@ -316,7 +316,6 @@ config ST_SLIM_REMOTEPROC · 133 unmodified lines
316316 config STM32_RPROC
317317 tristate "STM32 remoteproc support"
318318 depends on ARCH_STM32 || COMPILE_TEST
319− depends on REMOTEPROC
320319 select MAILBOX
321320 help
322321 Say y here to support STM32 MCU processors via the
drivers/remoteproc/imx_rproc.c+91−4
@@ -145,6 +145,41 @@ static const struct imx_rproc_att imx_rproc_att_imx95_m7[] = { · 144 unmodified lines
145145 { 0x80000000, 0x80000000, 0x50000000, 0 },
146146 };
147147
148+static const struct imx_rproc_att imx_rproc_att_imx94_m70[] = {
149+ /* dev addr , sys addr , size , flags */
150+ /* TCM CODE NON-SECURE */
151+ { 0x00000000, 0x203C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
152+ /* TCM SYS NON-SECURE*/
153+ { 0x20000000, 0x20400000, 0x00040000, ATT_OWN | ATT_IOMEM },
154+
155+ /* DDR */
156+ { 0x80000000, 0x80000000, 0x10000000, 0 },
157+};
158+
159+static const struct imx_rproc_att imx_rproc_att_imx94_m71[] = {
160+ /* dev addr , sys addr , size , flags */
161+ /* TCM CODE NON-SECURE */
162+ { 0x00000000, 0x202C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
163+ /* TCM SYS NON-SECURE*/
164+ { 0x20000000, 0x20300000, 0x00040000, ATT_OWN | ATT_IOMEM },
165+
166+ /* DDR */
167+ { 0x80000000, 0x80000000, 0x10000000, 0 },
168+};
169+
170+static const struct imx_rproc_att imx_rproc_att_imx94_m33s[] = {
171+ /* dev addr , sys addr , size , flags */
172+ /* TCM CODE NON-SECURE */
173+ { 0x0FFC0000, 0x209C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
174+ /* TCM SYS NON-SECURE */
175+ { 0x20000000, 0x20A00000, 0x00040000, ATT_OWN | ATT_IOMEM },
176+ /* M33S OCRAM NON-SECURE */
177+ { 0x20800000, 0x20800000, 0x180000, ATT_OWN | ATT_IOMEM },
178+
179+ /* DDR */
180+ { 0x80000000, 0x80000000, 0x10000000, 0 },
181+};
182+
148183 static const struct imx_rproc_att imx_rproc_att_imx93[] = {
149184 /* dev addr , sys addr , size , flags */
150185 /* TCM CODE NON-SECURE */
@@ -339,13 +374,32 @@ static int imx_rproc_scu_api_start(struct rproc *rproc) · 188 unmodified lines
339374 return imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, true, priv->entry);
340375 }
341376
377+static u64 imx_rproc_sm_get_reset_vector(struct rproc *rproc)
378+{
379+ struct imx_rproc *priv = rproc->priv;
380+ u32 reset_vector_mask = priv->dcfg->reset_vector_mask ?: GENMASK(31, 0);
381+
382+ /*
383+ * The hardware fetches the first two words from reset_vectors
384+ * (hardware reset address) and populates SP and PC using the first
385+ * two words. Execution proceeds from PC. The ELF entry point does
386+ * not always match the hardware reset address.
387+ * To derive the correct hardware reset address, the lower address
388+ * bits must be masked off before programming the reset vector.
389+ */
390+ return rproc->bootaddr & reset_vector_mask;
391+}
392+
342393 static int imx_rproc_sm_cpu_start(struct rproc *rproc)
343394 {
344395 struct imx_rproc *priv = rproc->priv;
345396 const struct imx_rproc_dcfg *dcfg = priv->dcfg;
397+ u64 reset_vector;
346398 int ret;
347399
348− ret = scmi_imx_cpu_reset_vector_set(dcfg->cpuid, 0, true, false, false);
400+ reset_vector = imx_rproc_sm_get_reset_vector(rproc);
401+
402+ ret = scmi_imx_cpu_reset_vector_set(dcfg->cpuid, reset_vector, true, false, false);
349403 if (ret) {
350404 dev_err(priv->dev, "Failed to set reset vector cpuid(%u): %d\n", dcfg->cpuid, ret);
351405 return ret;
@@ -359,13 +413,16 @@ static int imx_rproc_sm_lmm_start(struct rproc *rproc) · 7 unmodified lines
359413 struct imx_rproc *priv = rproc->priv;
360414 const struct imx_rproc_dcfg *dcfg = priv->dcfg;
361415 struct device *dev = priv->dev;
416+ u64 reset_vector;
362417 int ret;
363418
419+ reset_vector = imx_rproc_sm_get_reset_vector(rproc);
420+
364421 /*
365422 * If the remoteproc core can't start the M7, it will already be
366423 * handled in imx_rproc_sm_lmm_prepare().
367424 */
368− ret = scmi_imx_lmm_reset_vector_set(dcfg->lmid, dcfg->cpuid, 0, 0);
425+ ret = scmi_imx_lmm_reset_vector_set(dcfg->lmid, dcfg->cpuid, 0, reset_vector);
369426 if (ret) {
370427 dev_err(dev, "Failed to set reset vector lmid(%u), cpuid(%u): %d\n",
371428 dcfg->lmid, dcfg->cpuid, ret);
@@ -1230,8 +1287,7 @@ static int imx_rproc_probe(struct platform_device *pdev) · 858 unmodified lines
12301287 const struct imx_rproc_dcfg *dcfg;
12311288 int ret;
12321289
1233− /* set some other name then imx */
1234− rproc = devm_rproc_alloc(dev, "imx-rproc", &imx_rproc_ops,
1290+ rproc = devm_rproc_alloc(dev, np->name, &imx_rproc_ops,
12351291 NULL, sizeof(*priv));
12361292 if (!rproc)
12371293 return -ENOMEM;
@@ -1455,6 +1511,33 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = { · 217 unmodified lines
14551511 .flags = IMX_RPROC_NEED_CLKS,
14561512 };
14571513
1514+static const struct imx_rproc_dcfg imx_rproc_cfg_imx94_m70 = {
1515+ .att = imx_rproc_att_imx94_m70,
1516+ .att_size = ARRAY_SIZE(imx_rproc_att_imx94_m70),
1517+ .ops = &imx_rproc_ops_sm_lmm,
1518+ .cpuid = 1,
1519+ .lmid = 2,
1520+ .reset_vector_mask = GENMASK_U32(31, 16),
1521+};
1522+
1523+static const struct imx_rproc_dcfg imx_rproc_cfg_imx94_m71 = {
1524+ .att = imx_rproc_att_imx94_m71,
1525+ .att_size = ARRAY_SIZE(imx_rproc_att_imx94_m71),
1526+ .ops = &imx_rproc_ops_sm_lmm,
1527+ .cpuid = 7,
1528+ .lmid = 3,
1529+ .reset_vector_mask = GENMASK_U32(31, 16),
1530+};
1531+
1532+static const struct imx_rproc_dcfg imx_rproc_cfg_imx94_m33s = {
1533+ .att = imx_rproc_att_imx94_m33s,
1534+ .att_size = ARRAY_SIZE(imx_rproc_att_imx94_m33s),
1535+ .ops = &imx_rproc_ops_sm_lmm,
1536+ .cpuid = 8,
1537+ .lmid = 1,
1538+ .reset_vector_mask = GENMASK_U32(31, 16),
1539+};
1540+
14581541 static const struct imx_rproc_dcfg imx_rproc_cfg_imx95_m7 = {
14591542 .att = imx_rproc_att_imx95_m7,
14601543 .att_size = ARRAY_SIZE(imx_rproc_att_imx95_m7),
@@ -1462,6 +1545,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx95_m7 = { · 1 unmodified line
14621545 /* Must align with System Manager Firmware */
14631546 .cpuid = 1, /* Use 1 as cpu id for M7 core */
14641547 .lmid = 1, /* Use 1 as Logical Machine ID where M7 resides */
1548+ .reset_vector_mask = GENMASK_U32(31, 16),
14651549 };
14661550
14671551 static const struct of_device_id imx_rproc_of_match[] = {
@@ -1478,6 +1562,9 @@ static const struct of_device_id imx_rproc_of_match[] = { · 10 unmodified lines
14781562 { .compatible = "fsl,imx8qm-cm4", .data = &imx_rproc_cfg_imx8qm },
14791563 { .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp },
14801564 { .compatible = "fsl,imx93-cm33", .data = &imx_rproc_cfg_imx93 },
1565+ { .compatible = "fsl,imx94-cm70", .data = &imx_rproc_cfg_imx94_m70 },
1566+ { .compatible = "fsl,imx94-cm71", .data = &imx_rproc_cfg_imx94_m71 },
1567+ { .compatible = "fsl,imx94-cm33s", .data = &imx_rproc_cfg_imx94_m33s },
14811568 { .compatible = "fsl,imx95-cm7", .data = &imx_rproc_cfg_imx95_m7 },
14821569 {},
14831570 };
drivers/remoteproc/imx_rproc.h+2−0
@@ -41,6 +41,8 @@ struct imx_rproc_dcfg { · 40 unmodified lines
4141 /* For System Manager(SM) based SoCs */
4242 u32 cpuid; /* ID of the remote core */
4343 u32 lmid; /* ID of the Logcial Machine */
44+ /* reset_vector = elf_entry_addr & reset_vector_mask */
45+ u32 reset_vector_mask;
4446 };
4547
4648 #endif /* _IMX_RPROC_H */
drivers/remoteproc/qcom_common.c+10−4
@@ -109,6 +109,7 @@ static int qcom_add_minidump_segments(struct rproc *rproc, struct minidump_subsy · 108 unmodified lines
109109 struct minidump_region __iomem *ptr;
110110 struct minidump_region region;
111111 int seg_cnt, i;
112+ int ret = 0;
112113 dma_addr_t da;
113114 size_t size;
114115 char *name;
@@ -129,17 +130,22 @@ static int qcom_add_minidump_segments(struct rproc *rproc, struct minidump_subsy · 14 unmodified lines
129130 if (le32_to_cpu(region.valid) == MINIDUMP_REGION_VALID) {
130131 name = kstrndup(region.name, MAX_REGION_NAME_LENGTH - 1, GFP_KERNEL);
131132 if (!name) {
132− iounmap(ptr);
133− return -ENOMEM;
133+ ret = -ENOMEM;
134+ break;
134135 }
135136 da = le64_to_cpu(region.address);
136137 size = le64_to_cpu(region.size);
137− rproc_coredump_add_custom_segment(rproc, da, size, rproc_dumpfn_t, name);
138+ ret = rproc_coredump_add_custom_segment(rproc, da, size, rproc_dumpfn_t,
139+ name);
140+ if (ret) {
141+ kfree(name);
142+ break;
143+ }
138144 }
139145 }
140146
141147 iounmap(ptr);
142− return 0;
148+ return ret;
143149 }
144150
145151 void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
drivers/remoteproc/qcom_q6v5_pas.c+48−3
@@ -92,9 +92,6 @@ struct qcom_pas { · 91 unmodified lines
9292 const struct firmware *firmware;
9393 const struct firmware *dtb_firmware;
9494
95− struct completion start_done;
96− struct completion stop_done;
97−
9895 phys_addr_t mem_phys;
9996 phys_addr_t dtb_mem_phys;
10097 phys_addr_t mem_reloc;
@@ -1457,6 +1454,51 @@ static const struct qcom_pas_data sc7280_wpss_resource = { · 1356 unmodified lines
14571454 .ssctl_id = 0x19,
14581455 };
14591456
1457+static const struct qcom_pas_data shikra_cdsp_resource = {
1458+ .crash_reason_smem = 601,
1459+ .firmware_name = "cdsp.mbn",
1460+ .pas_id = 18,
1461+ .minidump_id = 7,
1462+ .auto_boot = true,
1463+ .proxy_pd_names = (char *[]){
1464+ "cx",
1465+ NULL
1466+ },
1467+ .load_state = "cdsp",
1468+ .ssr_name = "cdsp",
1469+ .sysmon_name = "cdsp",
1470+ .ssctl_id = 0x17,
1471+ .smem_host_id = 5,
1472+};
1473+
1474+static const struct qcom_pas_data shikra_lpaicp_resource = {
1475+ .crash_reason_smem = 682,
1476+ .firmware_name = "lpaicp.mbn",
1477+ .dtb_firmware_name = "lpaicp_dtb.mbn",
1478+ .pas_id = 0x56,
1479+ .dtb_pas_id = 0x57,
1480+ .minidump_id = 0,
1481+ .auto_boot = true,
1482+ .ssr_name = "lpaicp",
1483+ .sysmon_name = "lpaicp",
1484+};
1485+
1486+static const struct qcom_pas_data shikra_mpss_resource = {
1487+ .crash_reason_smem = 421,
1488+ .firmware_name = "qdsp6sw.mbn",
1489+ .pas_id = 4,
1490+ .minidump_id = 3,
1491+ .auto_boot = false,
1492+ .proxy_pd_names = (char *[]){
1493+ "cx",
1494+ NULL
1495+ },
1496+ .load_state = "modem",
1497+ .ssr_name = "mpss",
1498+ .sysmon_name = "modem",
1499+ .ssctl_id = 0x12,
1500+};
1501+
14601502 static const struct qcom_pas_data sm8650_cdsp_resource = {
14611503 .crash_reason_smem = 601,
14621504 .firmware_name = "cdsp.mdt",
@@ -1571,6 +1613,9 @@ static const struct of_device_id qcom_pas_of_match[] = { · 108 unmodified lines
15711613 { .compatible = "qcom,sdm845-slpi-pas", .data = &sdm845_slpi_resource_init },
15721614 { .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource },
15731615 { .compatible = "qcom,sdx75-mpss-pas", .data = &sm8650_mpss_resource },
1616+ { .compatible = "qcom,shikra-cdsp-pas", .data = &shikra_cdsp_resource },
1617+ { .compatible = "qcom,shikra-lpaicp-pas", .data = &shikra_lpaicp_resource },
1618+ { .compatible = "qcom,shikra-mpss-pas", .data = &shikra_mpss_resource },
15741619 { .compatible = "qcom,sm6115-adsp-pas", .data = &adsp_resource_init },
15751620 { .compatible = "qcom,sm6115-cdsp-pas", .data = &cdsp_resource_init },
15761621 { .compatible = "qcom,sm6115-mpss-pas", .data = &sc8180x_mpss_resource },
drivers/remoteproc/qcom_q6v5_wcss.c+5−18
@@ -96,7 +96,6 @@ struct wcss_data { · 95 unmodified lines
9696 unsigned int crash_reason_smem;
9797 u32 version;
9898 bool aon_reset_required;
99− bool wcss_q6_reset_required;
10099 const char *ssr_name;
101100 const char *sysmon_name;
102101 int ssctl_id;
@@ -134,7 +133,6 @@ struct q6v5_wcss { · 31 unmodified lines
134133 struct reset_control *wcss_aon_reset;
135134 struct reset_control *wcss_reset;
136135 struct reset_control *wcss_q6_reset;
137− struct reset_control *wcss_q6_bcr_reset;
138136
139137 struct qcom_q6v5 q6v5;
140138
@@ -309,7 +307,7 @@ static int q6v5_wcss_qcs404_power_on(struct q6v5_wcss *wcss) · 168 unmodified lines
309307 return ret;
310308
311309 /* Remove reset to the WCNSS QDSP6SS */
312− reset_control_deassert(wcss->wcss_q6_bcr_reset);
310+ reset_control_deassert(wcss->wcss_q6_reset);
313311
314312 /* Enable Q6SSTOP_AHBFABRIC_CBCR clock */
315313 ret = clk_prepare_enable(wcss->ahbfabric_cbcr_clk);
@@ -803,19 +801,10 @@ static int q6v5_wcss_init_reset(struct q6v5_wcss *wcss, · 487 unmodified lines
803801 return PTR_ERR(wcss->wcss_reset);
804802 }
805803
806− if (desc->wcss_q6_reset_required) {
807− wcss->wcss_q6_reset = devm_reset_control_get_exclusive(dev, "wcss_q6_reset");
808− if (IS_ERR(wcss->wcss_q6_reset)) {
809− dev_err(wcss->dev, "unable to acquire wcss_q6_reset\n");
810− return PTR_ERR(wcss->wcss_q6_reset);
811− }
812− }
813−
814− wcss->wcss_q6_bcr_reset = devm_reset_control_get_optional_exclusive(dev,
815− "wcss_q6_bcr_reset");
816− if (IS_ERR(wcss->wcss_q6_bcr_reset)) {
817− dev_err(wcss->dev, "unable to acquire wcss_q6_bcr_reset\n");
818− return PTR_ERR(wcss->wcss_q6_bcr_reset);
804+ wcss->wcss_q6_reset = devm_reset_control_get_exclusive(dev, "wcss_q6_reset");
805+ if (IS_ERR(wcss->wcss_q6_reset)) {
806+ dev_err(wcss->dev, "unable to acquire wcss_q6_reset\n");
807+ return PTR_ERR(wcss->wcss_q6_reset);
819808 }
820809
821810 return 0;
@@ -1062,7 +1051,6 @@ static const struct wcss_data wcss_ipq8074_res_init = { · 240 unmodified lines
10621051 .firmware_name = "IPQ8074/q6_fw.mdt",
10631052 .crash_reason_smem = WCSS_CRASH_REASON,
10641053 .aon_reset_required = true,
1065− .wcss_q6_reset_required = true,
10661054 .ops = &q6v5_wcss_ipq8074_ops,
10671055 .requires_force_stop = true,
10681056 };
@@ -1072,7 +1060,6 @@ static const struct wcss_data wcss_qcs404_res_init = { · 3 unmodified lines
10721060 .firmware_name = "wcnss.mdt",
10731061 .version = WCSS_QCS404,
10741062 .aon_reset_required = false,
1075− .wcss_q6_reset_required = false,
10761063 .ssr_name = "mpss",
10771064 .sysmon_name = "wcnss",
10781065 .ssctl_id = 0x12,
drivers/remoteproc/remoteproc_core.c+38−43
@@ -1011,60 +1011,55 @@ static rproc_handle_resource_t rproc_loading_handlers[RSC_LAST] = { · 1010 unmodified lines
10111011 [RSC_VDEV] = rproc_handle_vdev,
10121012 };
10131013
1014−/* handle firmware resource entries before booting the remote processor */
1015−static int rproc_handle_resources(struct rproc *rproc,
1016− rproc_handle_resource_t handlers[RSC_LAST])
1014+struct rproc_rsc_cb_data {
1015+ struct rproc *rproc;
1016+ rproc_handle_resource_t *handlers;
1017+};
1018+
1019+static int rproc_handle_rsc_entry(u32 type, void *rsc, int offset,
1020+ int avail, void *data)
10171021 {
1022+ struct rproc_rsc_cb_data *d = data;
1023+ struct rproc *rproc = d->rproc;
10181024 struct device *dev = &rproc->dev;
10191025 rproc_handle_resource_t handler;
1020− int ret = 0, i;
1021−
1022− if (!rproc->table_ptr)
1023− return 0;
1026+ int ret;
10241027
1025− for (i = 0; i < rproc->table_ptr->num; i++) {
1026− int offset = rproc->table_ptr->offset[i];
1027− struct fw_rsc_hdr *hdr = (void *)rproc->table_ptr + offset;
1028− int avail = rproc->table_sz - offset - sizeof(*hdr);
1029− void *rsc = (void *)hdr + sizeof(*hdr);
1028+ dev_dbg(dev, "rsc: type %d\n", type);
10301029
1031− /* make sure table isn't truncated */
1032− if (avail < 0) {
1033− dev_err(dev, "rsc table is truncated\n");
1034− return -EINVAL;
1035− }
1036−
1037− dev_dbg(dev, "rsc: type %d\n", hdr->type);
1030+ if (type >= RSC_VENDOR_START && type <= RSC_VENDOR_END) {
1031+ ret = rproc_handle_rsc(rproc, type, rsc, offset, avail);
1032+ if (ret == RSC_HANDLED)
1033+ return 0;
1034+ if (ret < 0)
1035+ return ret;
1036+ dev_warn(dev, "unsupported vendor resource %d\n", type);
1037+ return 0;
1038+ }
10381039
1039− if (hdr->type >= RSC_VENDOR_START &&
1040− hdr->type <= RSC_VENDOR_END) {
1041− ret = rproc_handle_rsc(rproc, hdr->type, rsc,
1042− offset + sizeof(*hdr), avail);
1043− if (ret == RSC_HANDLED)
1044− continue;
1045− else if (ret < 0)
1046− break;
1040+ if (type >= RSC_LAST) {
1041+ dev_warn(dev, "unsupported resource %d\n", type);
1042+ return 0;
1043+ }
10471044
1048− dev_warn(dev, "unsupported vendor resource %d\n",
1049− hdr->type);
1050− continue;
1051− }
1045+ handler = d->handlers[type];
1046+ if (!handler)
1047+ return 0;
10521048
1053− if (hdr->type >= RSC_LAST) {
1054− dev_warn(dev, "unsupported resource %d\n", hdr->type);
1055− continue;
1056− }
1049+ return handler(rproc, rsc, offset, avail);
1050+}
10571051
1058− handler = handlers[hdr->type];
1059− if (!handler)
1060− continue;
1052+/* handle firmware resource entries before booting the remote processor */
1053+static int rproc_handle_resources(struct rproc *rproc,
1054+ rproc_handle_resource_t handlers[RSC_LAST])
1055+{
1056+ struct rproc_rsc_cb_data d = { .rproc = rproc, .handlers = handlers };
10611057
1062− ret = handler(rproc, rsc, offset + sizeof(*hdr), avail);
1063− if (ret)
1064− break;
1065− }
1058+ if (!rproc->table_ptr)
1059+ return 0;
10661060
1067− return ret;
1061+ return rsc_table_for_each_entry(rproc->table_ptr, rproc->table_sz,
1062+ &rproc->dev, rproc_handle_rsc_entry, &d);
10681063 }
10691064
10701065 static int rproc_prepare_subdevices(struct rproc *rproc)
drivers/remoteproc/xlnx_r5_remoteproc.c+75−25
@@ -4,7 +4,6 @@ · 3 unmodified lines
44 *
55 */
66
7−#include <dt-bindings/power/xlnx-zynqmp-power.h>
87 #include <linux/dma-mapping.h>
98 #include <linux/firmware/xlnx-zynqmp.h>
109 #include <linux/kernel.h>
@@ -19,6 +18,11 @@ · 8 unmodified lines
1918
2019 #include "remoteproc_internal.h"
2120
21+#define PD_R5_0_ATCM 15
22+#define PD_R5_0_BTCM 16
23+#define PD_R5_1_ATCM 17
24+#define PD_R5_1_BTCM 18
25+
2226 /* IPI buffer MAX length */
2327 #define IPI_BUF_LEN_MAX 32U
2428
@@ -899,17 +903,18 @@ static const struct rproc_ops zynqmp_r5_rproc_ops = { · 874 unmodified lines
899903 };
900904
901905 /**
902− * zynqmp_r5_add_rproc_core() - Add core data to framework.
903− * Allocate and add struct rproc object for each r5f core
906+ * zynqmp_r5_alloc_rproc_core() - alloc rproc core data structure
907+ * Allocate struct rproc object for each r5f core
904908 * This is called for each individual r5f core
905909 *
906910 * @cdev: Device node of each r5 core
907911 *
908912 * Return: zynqmp_r5_core object for success else error code pointer
909913 */
910−static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
914+static struct zynqmp_r5_core *zynqmp_r5_alloc_rproc_core(struct device *cdev)
911915 {
912916 struct zynqmp_r5_core *r5_core;
917+ const char *fw_name = NULL;
913918 struct rproc *r5_rproc;
914919 int ret;
915920
@@ -918,10 +923,15 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev) · 2 unmodified lines
918923 if (ret)
919924 return ERR_PTR(ret);
920925
926+ ret = rproc_of_parse_firmware(cdev, 0, &fw_name);
927+ if (ret < 0 && ret != -EINVAL)
928+ return ERR_PTR(dev_err_probe(cdev, ret,
929+ "failed to parse firmware-name\n"));
930+
921931 /* Allocate remoteproc instance */
922932 r5_rproc = rproc_alloc(cdev, dev_name(cdev),
923933 &zynqmp_r5_rproc_ops,
924− NULL, sizeof(struct zynqmp_r5_core));
934+ fw_name, sizeof(struct zynqmp_r5_core));
925935 if (!r5_rproc) {
926936 dev_err(cdev, "failed to allocate memory for rproc instance\n");
927937 return ERR_PTR(-ENOMEM);
@@ -932,6 +942,11 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev) · 4 unmodified lines
932942 r5_rproc->recovery_disabled = true;
933943 r5_rproc->has_iommu = false;
934944 r5_rproc->auto_boot = false;
945+
946+ /* attempt to boot automatically if the firmware-name is provided */
947+ if (fw_name)
948+ r5_rproc->auto_boot = true;
949+
935950 r5_core = r5_rproc->priv;
936951 r5_core->dev = cdev;
937952 r5_core->np = dev_of_node(cdev);
@@ -941,23 +956,6 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev) · 3 unmodified lines
941956 goto free_rproc;
942957 }
943958
944− /* Add R5 remoteproc core */
945− ret = rproc_add(r5_rproc);
946− if (ret) {
947− dev_err(cdev, "failed to add r5 remoteproc\n");
948− goto free_rproc;
949− }
950−
951− /*
952− * If firmware is already available in the memory then move rproc state
953− * to DETACHED. Firmware can be preloaded via debugger or by any other
954− * agent (processors) in the system.
955− * If firmware isn't available in the memory and resource table isn't
956− * found, then rproc state remains OFFLINE.
957− */
958− if (!zynqmp_r5_get_rsc_table_va(r5_core))
959− r5_rproc->state = RPROC_DETACHED;
960−
961959 r5_core->rproc = r5_rproc;
962960 return r5_core;
963961
@@ -1210,6 +1208,7 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster, · 246 unmodified lines
12101208 {
12111209 struct device *dev = cluster->dev;
12121210 struct zynqmp_r5_core *r5_core;
1211+ u32 req, usage, status;
12131212 int ret = -EINVAL, i;
12141213
12151214 r5_core = cluster->r5_cores[0];
@@ -1255,6 +1254,42 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster, · 39 unmodified lines
12551254 ret = zynqmp_r5_get_sram_banks(r5_core);
12561255 if (ret)
12571256 return ret;
1257+
1258+ /*
1259+ * It is possible that firmware is loaded into the memory, but
1260+ * RPU (remote) is not running. In such case, RPU state will be
1261+ * moved to RPROC_DETACHED wrongfully. To avoid it first make
1262+ * sure RPU is power-on and out of reset before parsing for the
1263+ * resource table.
1264+ */
1265+ ret = zynqmp_pm_get_rpu_node_status(r5_core->pm_domain_id,
1266+ &status, &req, &usage);
1267+ if (ret) {
1268+ dev_warn(r5_core->dev,
1269+ "failed to get rpu node status, err %d\n", ret);
1270+ continue;
1271+ }
1272+
1273+ /*
1274+ * If RPU state is power on and out of reset i.e. running, then
1275+ * assign RPROC_DETACHED state. If the RPU is not out of reset
1276+ * then do not attempt to attach to the remote processor.
1277+ */
1278+ if (status == PM_NODE_RUNNING) {
1279+ /*
1280+ * Not all the firmware that is running on the remote
1281+ * core is expected to have the resource table. The
1282+ * firmware might not use RPMsg at all, and in that case
1283+ * resource table becomes irrelevant. However, we still
1284+ * need to make sure that running core is not reported
1285+ * as offline. so do not decide remote core state based
1286+ * on the resource table availability
1287+ */
1288+ if (zynqmp_r5_get_rsc_table_va(r5_core))
1289+ dev_dbg(r5_core->dev, "rsc tbl not found\n");
1290+ r5_core->rproc->state = RPROC_DETACHED;
1291+ r5_core->rproc->auto_boot = true;
1292+ }
12581293 }
12591294
12601295 return 0;
@@ -1278,7 +1313,7 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster) · 17 unmodified lines
12781313 enum rpu_oper_mode fw_reg_val;
12791314 struct device **child_devs;
12801315 enum rpu_tcm_comb tcm_mode;
1281− int core_count, ret, i;
1316+ int core_count, ret, i, j;
12821317 struct mbox_info *ipi;
12831318
12841319 ret = of_property_read_u32(dev_node, "xlnx,cluster-mode", &cluster_mode);
@@ -1364,7 +1399,7 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster) · 79 unmodified lines
13641399 child_devs[i] = &child_pdev->dev;
13651400
13661401 /* create and add remoteproc instance of type struct rproc */
1367− r5_cores[i] = zynqmp_r5_add_rproc_core(&child_pdev->dev);
1402+ r5_cores[i] = zynqmp_r5_alloc_rproc_core(&child_pdev->dev);
13681403 if (IS_ERR(r5_cores[i])) {
13691404 ret = PTR_ERR(r5_cores[i]);
13701405 r5_cores[i] = NULL;
@@ -1409,16 +1444,31 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster) · 38 unmodified lines
14091444 goto release_r5_cores;
14101445 }
14111446
1447+ for (j = 0; j < cluster->core_count; j++) {
1448+ /* Add R5 remoteproc core */
1449+ ret = rproc_add(r5_cores[j]->rproc);
1450+ if (ret) {
1451+ dev_err_probe(r5_cores[j]->dev, ret,
1452+ "failed to add remoteproc\n");
1453+ goto delete_r5_cores;
1454+ }
1455+ }
1456+
14121457 kfree(child_devs);
14131458 return 0;
14141459
1460+delete_r5_cores:
1461+ i = core_count - 1;
1462+ /* delete previous added rproc */
1463+ while (--j >= 0)
1464+ rproc_del(r5_cores[j]->rproc);
1465+
14151466 release_r5_cores:
14161467 while (i >= 0) {
14171468 put_device(child_devs[i]);
14181469 if (r5_cores[i]) {
14191470 zynqmp_r5_free_mbox(r5_cores[i]->ipi);
14201471 of_reserved_mem_device_release(r5_cores[i]->dev);
1421− rproc_del(r5_cores[i]->rproc);
14221472 rproc_free(r5_cores[i]->rproc);
14231473 }
14241474 i--;
include/linux/firmware/xlnx-zynqmp.h+21−0
@@ -542,6 +542,18 @@ enum pm_gem_config_type { · 541 unmodified lines
542542 GEM_CONFIG_FIXED = 2,
543543 };
544544
545+/**
546+ * enum pm_node_status - Device node status provided by xilpm fw
547+ * @PM_NODE_UNUSED: Device is not used
548+ * @PM_NODE_RUNNING: Device is power-on and out of reset
549+ * @PM_NODE_HALT: Device is power-on but in the reset state
550+ */
551+enum pm_node_status {
552+ PM_NODE_UNUSED = 0,
553+ PM_NODE_RUNNING = 1,
554+ PM_NODE_HALT = 12,
555+};
556+
545557 /**
546558 * struct zynqmp_pm_query_data - PM query data
547559 * @qid: query ID
@@ -630,6 +642,8 @@ int zynqmp_pm_set_rpu_mode(u32 node_id, enum rpu_oper_mode rpu_mode); · 82 unmodified lines
630642 int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mode);
631643 int zynqmp_pm_get_node_status(const u32 node, u32 *const status,
632644 u32 *const requirements, u32 *const usage);
645+int zynqmp_pm_get_rpu_node_status(const u32 node, u32 *const status,
646+ u32 *const requirements, u32 *const usage);
633647 int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value);
634648 int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config,
635649 u32 value);
@@ -939,6 +953,13 @@ static inline int zynqmp_pm_get_node_status(const u32 node, u32 *const status, · 303 unmodified lines
939953 return -ENODEV;
940954 }
941955
956+static inline int zynqmp_pm_get_rpu_node_status(const u32 node, u32 *const status,
957+ u32 *const requirements,
958+ u32 *const usage)
959+{
960+ return -ENODEV;
961+}
962+
942963 static inline int zynqmp_pm_set_sd_config(u32 node,
943964 enum pm_sd_config_type config,
944965 u32 value)
include/linux/remoteproc.h+1−268
@@ -42,274 +42,7 @@ · 41 unmodified lines
4242 #include <linux/completion.h>
4343 #include <linux/idr.h>
4444 #include <linux/of.h>
45−
46−/**
47− * struct resource_table - firmware resource table header
48− * @ver: version number
49− * @num: number of resource entries
50− * @reserved: reserved (must be zero)
51− * @offset: array of offsets pointing at the various resource entries
52− *
53− * A resource table is essentially a list of system resources required
54− * by the remote processor. It may also include configuration entries.
55− * If needed, the remote processor firmware should contain this table
56− * as a dedicated ".resource_table" ELF section.
57− *
58− * Some resources entries are mere announcements, where the host is informed
59− * of specific remoteproc configuration. Other entries require the host to
60− * do something (e.g. allocate a system resource). Sometimes a negotiation
61− * is expected, where the firmware requests a resource, and once allocated,
62− * the host should provide back its details (e.g. address of an allocated
63− * memory region).
64− *
65− * The header of the resource table, as expressed by this structure,
66− * contains a version number (should we need to change this format in the
67− * future), the number of available resource entries, and their offsets
68− * in the table.
69− *
70− * Immediately following this header are the resource entries themselves,
71− * each of which begins with a resource entry header (as described below).
72− */
73−struct resource_table {
74− u32 ver;
75− u32 num;
76− u32 reserved[2];
77− u32 offset[];
78−} __packed;
79−
80−/**
81− * struct fw_rsc_hdr - firmware resource entry header
82− * @type: resource type
83− * @data: resource data
84− *
85− * Every resource entry begins with a 'struct fw_rsc_hdr' header providing
86− * its @type. The content of the entry itself will immediately follow
87− * this header, and it should be parsed according to the resource type.
88− */
89−struct fw_rsc_hdr {
90− u32 type;
91− u8 data[];
92−} __packed;
93−
94−/**
95− * enum fw_resource_type - types of resource entries
96− *
97− * @RSC_CARVEOUT: request for allocation of a physically contiguous
98− * memory region.
99− * @RSC_DEVMEM: request to iommu_map a memory-based peripheral.
100− * @RSC_TRACE: announces the availability of a trace buffer into which
101− * the remote processor will be writing logs.
102− * @RSC_VDEV: declare support for a virtio device, and serve as its
103− * virtio header.
104− * @RSC_LAST: just keep this one at the end of standard resources
105− * @RSC_VENDOR_START: start of the vendor specific resource types range
106− * @RSC_VENDOR_END: end of the vendor specific resource types range
107− *
108− * For more details regarding a specific resource type, please see its
109− * dedicated structure below.
110− *
111− * Please note that these values are used as indices to the rproc_handle_rsc
112− * lookup table, so please keep them sane. Moreover, @RSC_LAST is used to
113− * check the validity of an index before the lookup table is accessed, so
114− * please update it as needed.
115− */
116−enum fw_resource_type {
117− RSC_CARVEOUT = 0,
118− RSC_DEVMEM = 1,
119− RSC_TRACE = 2,
120− RSC_VDEV = 3,
121− RSC_LAST = 4,
122− RSC_VENDOR_START = 128,
123− RSC_VENDOR_END = 512,
124−};
125−
126−#define FW_RSC_ADDR_ANY (-1)
127−
128−/**
129− * struct fw_rsc_carveout - physically contiguous memory request
130− * @da: device address
131− * @pa: physical address
132− * @len: length (in bytes)
133− * @flags: iommu protection flags
134− * @reserved: reserved (must be zero)
135− * @name: human-readable name of the requested memory region
136− *
137− * This resource entry requests the host to allocate a physically contiguous
138− * memory region.
139− *
140− * These request entries should precede other firmware resource entries,
141− * as other entries might request placing other data objects inside
142− * these memory regions (e.g. data/code segments, trace resource entries, ...).
143− *
144− * Allocating memory this way helps utilizing the reserved physical memory
145− * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries
146− * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB
147− * pressure is important; it may have a substantial impact on performance.
148− *
149− * If the firmware is compiled with static addresses, then @da should specify
150− * the expected device address of this memory region. If @da is set to
151− * FW_RSC_ADDR_ANY, then the host will dynamically allocate it, and then
152− * overwrite @da with the dynamically allocated address.
153− *
154− * We will always use @da to negotiate the device addresses, even if it
155− * isn't using an iommu. In that case, though, it will obviously contain
156− * physical addresses.
157− *
158− * Some remote processors needs to know the allocated physical address
159− * even if they do use an iommu. This is needed, e.g., if they control
160− * hardware accelerators which access the physical memory directly (this
161− * is the case with OMAP4 for instance). In that case, the host will
162− * overwrite @pa with the dynamically allocated physical address.
163− * Generally we don't want to expose physical addresses if we don't have to
164− * (remote processors are generally _not_ trusted), so we might want to
165− * change this to happen _only_ when explicitly required by the hardware.
166− *
167− * @flags is used to provide IOMMU protection flags, and @name should
168− * (optionally) contain a human readable name of this carveout region
169− * (mainly for debugging purposes).
170− */
171−struct fw_rsc_carveout {
172− u32 da;
173− u32 pa;
174− u32 len;
175− u32 flags;
176− u32 reserved;
177− u8 name[32];
178−} __packed;
179−
180−/**
181− * struct fw_rsc_devmem - iommu mapping request
182− * @da: device address
183− * @pa: physical address
184− * @len: length (in bytes)
185− * @flags: iommu protection flags
186− * @reserved: reserved (must be zero)
187− * @name: human-readable name of the requested region to be mapped
188− *
189− * This resource entry requests the host to iommu map a physically contiguous
190− * memory region. This is needed in case the remote processor requires
191− * access to certain memory-based peripherals; _never_ use it to access
192− * regular memory.
193− *
194− * This is obviously only needed if the remote processor is accessing memory
195− * via an iommu.
196− *
197− * @da should specify the required device address, @pa should specify
198− * the physical address we want to map, @len should specify the size of
199− * the mapping and @flags is the IOMMU protection flags. As always, @name may
200− * (optionally) contain a human readable name of this mapping (mainly for
201− * debugging purposes).
202− *
203− * Note: at this point we just "trust" those devmem entries to contain valid
204− * physical addresses, but this isn't safe and will be changed: eventually we
205− * want remoteproc implementations to provide us ranges of physical addresses
206− * the firmware is allowed to request, and not allow firmwares to request
207− * access to physical addresses that are outside those ranges.
208− */
209−struct fw_rsc_devmem {
210− u32 da;
211− u32 pa;
212− u32 len;
213− u32 flags;
214− u32 reserved;
215− u8 name[32];
216−} __packed;
217−
218−/**
219− * struct fw_rsc_trace - trace buffer declaration
220− * @da: device address
221− * @len: length (in bytes)
222− * @reserved: reserved (must be zero)
223− * @name: human-readable name of the trace buffer
224− *
225− * This resource entry provides the host information about a trace buffer
226− * into which the remote processor will write log messages.
227− *
228− * @da specifies the device address of the buffer, @len specifies
229− * its size, and @name may contain a human readable name of the trace buffer.
230− *
231− * After booting the remote processor, the trace buffers are exposed to the
232− * user via debugfs entries (called trace0, trace1, etc..).
233− */
234−struct fw_rsc_trace {
235− u32 da;
236− u32 len;
237− u32 reserved;
238− u8 name[32];
239−} __packed;
240−
241−/**
242− * struct fw_rsc_vdev_vring - vring descriptor entry
243− * @da: device address
244− * @align: the alignment between the consumer and producer parts of the vring
245− * @num: num of buffers supported by this vring (must be power of two)
246− * @notifyid: a unique rproc-wide notify index for this vring. This notify
247− * index is used when kicking a remote processor, to let it know that this
248− * vring is triggered.
249− * @pa: physical address
250− *
251− * This descriptor is not a resource entry by itself; it is part of the
252− * vdev resource type (see below).
253− *
254− * Note that @da should either contain the device address where
255− * the remote processor is expecting the vring, or indicate that
256− * dynamically allocation of the vring's device address is supported.
257− */
258−struct fw_rsc_vdev_vring {
259− u32 da;
260− u32 align;
261− u32 num;
262− u32 notifyid;
263− u32 pa;
264−} __packed;
265−
266−/**
267− * struct fw_rsc_vdev - virtio device header
268− * @id: virtio device id (as in virtio_ids.h)
269− * @notifyid: a unique rproc-wide notify index for this vdev. This notify
270− * index is used when kicking a remote processor, to let it know that the
271− * status/features of this vdev have changes.
272− * @dfeatures: specifies the virtio device features supported by the firmware
273− * @gfeatures: a place holder used by the host to write back the
274− * negotiated features that are supported by both sides.
275− * @config_len: the size of the virtio config space of this vdev. The config
276− * space lies in the resource table immediate after this vdev header.
277− * @status: a place holder where the host will indicate its virtio progress.
278− * @num_of_vrings: indicates how many vrings are described in this vdev header
279− * @reserved: reserved (must be zero)
280− * @vring: an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'.
281− *
282− * This resource is a virtio device header: it provides information about
283− * the vdev, and is then used by the host and its peer remote processors
284− * to negotiate and share certain virtio properties.
285− *
286− * By providing this resource entry, the firmware essentially asks remoteproc
287− * to statically allocate a vdev upon registration of the rproc (dynamic vdev
288− * allocation is not yet supported).
289− *
290− * Note:
291− * 1. unlike virtualization systems, the term 'host' here means
292− * the Linux side which is running remoteproc to control the remote
293− * processors. We use the name 'gfeatures' to comply with virtio's terms,
294− * though there isn't really any virtualized guest OS here: it's the host
295− * which is responsible for negotiating the final features.
296− * Yeah, it's a bit confusing.
297− *
298− * 2. immediately following this structure is the virtio config space for
299− * this vdev (which is specific to the vdev; for more info, read the virtio
300− * spec). The size of the config space is specified by @config_len.
301− */
302−struct fw_rsc_vdev {
303− u32 id;
304− u32 notifyid;
305− u32 dfeatures;
306− u32 gfeatures;
307− u32 config_len;
308− u8 status;
309− u8 num_of_vrings;
310− u8 reserved[2];
311− struct fw_rsc_vdev_vring vring[];
312−} __packed;
45+#include <linux/rsc_table.h>
31346
31447 struct rproc;
31548
include/linux/rsc_table.h+359−0
@@ -0,0 +1,359 @@
1+/*
2+ * Resource table and its types data structure
3+ *
4+ * Copyright(c) 2011 Texas Instruments, Inc.
5+ * Copyright(c) 2011 Google, Inc.
6+ * All rights reserved.
7+ *
8+ * Redistribution and use in source and binary forms, with or without
9+ * modification, are permitted provided that the following conditions
10+ * are met:
11+ *
12+ * * Redistributions of source code must retain the above copyright
13+ * notice, this list of conditions and the following disclaimer.
14+ * * Redistributions in binary form must reproduce the above copyright
15+ * notice, this list of conditions and the following disclaimer in
16+ * the documentation and/or other materials provided with the
17+ * distribution.
18+ * * Neither the name Texas Instruments nor the names of its
19+ * contributors may be used to endorse or promote products derived
20+ * from this software without specific prior written permission.
21+ *
22+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33+ */
34+
35+#ifndef RSC_TABLE_H
36+#define RSC_TABLE_H
37+
38+/**
39+ * struct resource_table - firmware resource table header
40+ * @ver: version number
41+ * @num: number of resource entries
42+ * @reserved: reserved (must be zero)
43+ * @offset: array of offsets pointing at the various resource entries
44+ *
45+ * A resource table is essentially a list of system resources required
46+ * by the remote processor. It may also include configuration entries.
47+ * If needed, the remote processor firmware should contain this table
48+ * as a dedicated ".resource_table" ELF section.
49+ *
50+ * Some resources entries are mere announcements, where the host is informed
51+ * of specific remoteproc configuration. Other entries require the host to
52+ * do something (e.g. allocate a system resource). Sometimes a negotiation
53+ * is expected, where the firmware requests a resource, and once allocated,
54+ * the host should provide back its details (e.g. address of an allocated
55+ * memory region).
56+ *
57+ * The header of the resource table, as expressed by this structure,
58+ * contains a version number (should we need to change this format in the
59+ * future), the number of available resource entries, and their offsets
60+ * in the table.
61+ *
62+ * Immediately following this header are the resource entries themselves,
63+ * each of which begins with a resource entry header (as described below).
64+ */
65+struct resource_table {
66+ u32 ver;
67+ u32 num;
68+ u32 reserved[2];
69+ u32 offset[];
70+} __packed;
71+
72+/**
73+ * struct fw_rsc_hdr - firmware resource entry header
74+ * @type: resource type
75+ * @data: resource data
76+ *
77+ * Every resource entry begins with a 'struct fw_rsc_hdr' header providing
78+ * its @type. The content of the entry itself will immediately follow
79+ * this header, and it should be parsed according to the resource type.
80+ */
81+struct fw_rsc_hdr {
82+ u32 type;
83+ u8 data[];
84+} __packed;
85+
86+/**
87+ * enum fw_resource_type - types of resource entries
88+ *
89+ * @RSC_CARVEOUT: request for allocation of a physically contiguous
90+ * memory region.
91+ * @RSC_DEVMEM: request to iommu_map a memory-based peripheral.
92+ * @RSC_TRACE: announces the availability of a trace buffer into which
93+ * the remote processor will be writing logs.
94+ * @RSC_VDEV: declare support for a virtio device, and serve as its
95+ * virtio header.
96+ * @RSC_LAST: just keep this one at the end of standard resources
97+ * @RSC_VENDOR_START: start of the vendor specific resource types range
98+ * @RSC_VENDOR_END: end of the vendor specific resource types range
99+ *
100+ * For more details regarding a specific resource type, please see its
101+ * dedicated structure below.
102+ *
103+ * Please note that these values are used as indices to the rproc_handle_rsc
104+ * lookup table, so please keep them sane. Moreover, @RSC_LAST is used to
105+ * check the validity of an index before the lookup table is accessed, so
106+ * please update it as needed.
107+ */
108+enum fw_resource_type {
109+ RSC_CARVEOUT = 0,
110+ RSC_DEVMEM = 1,
111+ RSC_TRACE = 2,
112+ RSC_VDEV = 3,
113+ RSC_LAST = 4,
114+ RSC_VENDOR_START = 128,
115+ RSC_VENDOR_END = 512,
116+};
117+
118+#define FW_RSC_ADDR_ANY (-1)
119+
120+/**
121+ * struct fw_rsc_carveout - physically contiguous memory request
122+ * @da: device address
123+ * @pa: physical address
124+ * @len: length (in bytes)
125+ * @flags: iommu protection flags
126+ * @reserved: reserved (must be zero)
127+ * @name: human-readable name of the requested memory region
128+ *
129+ * This resource entry requests the host to allocate a physically contiguous
130+ * memory region.
131+ *
132+ * These request entries should precede other firmware resource entries,
133+ * as other entries might request placing other data objects inside
134+ * these memory regions (e.g. data/code segments, trace resource entries, ...).
135+ *
136+ * Allocating memory this way helps utilizing the reserved physical memory
137+ * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries
138+ * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB
139+ * pressure is important; it may have a substantial impact on performance.
140+ *
141+ * If the firmware is compiled with static addresses, then @da should specify
142+ * the expected device address of this memory region. If @da is set to
143+ * FW_RSC_ADDR_ANY, then the host will dynamically allocate it, and then
144+ * overwrite @da with the dynamically allocated address.
145+ *
146+ * We will always use @da to negotiate the device addresses, even if it
147+ * isn't using an iommu. In that case, though, it will obviously contain
148+ * physical addresses.
149+ *
150+ * Some remote processors needs to know the allocated physical address
151+ * even if they do use an iommu. This is needed, e.g., if they control
152+ * hardware accelerators which access the physical memory directly (this
153+ * is the case with OMAP4 for instance). In that case, the host will
154+ * overwrite @pa with the dynamically allocated physical address.
155+ * Generally we don't want to expose physical addresses if we don't have to
156+ * (remote processors are generally _not_ trusted), so we might want to
157+ * change this to happen _only_ when explicitly required by the hardware.
158+ *
159+ * @flags is used to provide IOMMU protection flags, and @name should
160+ * (optionally) contain a human readable name of this carveout region
161+ * (mainly for debugging purposes).
162+ */
163+struct fw_rsc_carveout {
164+ u32 da;
165+ u32 pa;
166+ u32 len;
167+ u32 flags;
168+ u32 reserved;
169+ u8 name[32];
170+} __packed;
171+
172+/**
173+ * struct fw_rsc_devmem - iommu mapping request
174+ * @da: device address
175+ * @pa: physical address
176+ * @len: length (in bytes)
177+ * @flags: iommu protection flags
178+ * @reserved: reserved (must be zero)
179+ * @name: human-readable name of the requested region to be mapped
180+ *
181+ * This resource entry requests the host to iommu map a physically contiguous
182+ * memory region. This is needed in case the remote processor requires
183+ * access to certain memory-based peripherals; _never_ use it to access
184+ * regular memory.
185+ *
186+ * This is obviously only needed if the remote processor is accessing memory
187+ * via an iommu.
188+ *
189+ * @da should specify the required device address, @pa should specify
190+ * the physical address we want to map, @len should specify the size of
191+ * the mapping and @flags is the IOMMU protection flags. As always, @name may
192+ * (optionally) contain a human readable name of this mapping (mainly for
193+ * debugging purposes).
194+ *
195+ * Note: at this point we just "trust" those devmem entries to contain valid
196+ * physical addresses, but this isn't safe and will be changed: eventually we
197+ * want remoteproc implementations to provide us ranges of physical addresses
198+ * the firmware is allowed to request, and not allow firmwares to request
199+ * access to physical addresses that are outside those ranges.
200+ */
201+struct fw_rsc_devmem {
202+ u32 da;
203+ u32 pa;
204+ u32 len;
205+ u32 flags;
206+ u32 reserved;
207+ u8 name[32];
208+} __packed;
209+
210+/**
211+ * struct fw_rsc_trace - trace buffer declaration
212+ * @da: device address
213+ * @len: length (in bytes)
214+ * @reserved: reserved (must be zero)
215+ * @name: human-readable name of the trace buffer
216+ *
217+ * This resource entry provides the host information about a trace buffer
218+ * into which the remote processor will write log messages.
219+ *
220+ * @da specifies the device address of the buffer, @len specifies
221+ * its size, and @name may contain a human readable name of the trace buffer.
222+ *
223+ * After booting the remote processor, the trace buffers are exposed to the
224+ * user via debugfs entries (called trace0, trace1, etc..).
225+ */
226+struct fw_rsc_trace {
227+ u32 da;
228+ u32 len;
229+ u32 reserved;
230+ u8 name[32];
231+} __packed;
232+
233+/**
234+ * struct fw_rsc_vdev_vring - vring descriptor entry
235+ * @da: device address
236+ * @align: the alignment between the consumer and producer parts of the vring
237+ * @num: num of buffers supported by this vring (must be power of two)
238+ * @notifyid: a unique rproc-wide notify index for this vring. This notify
239+ * index is used when kicking a remote processor, to let it know that this
240+ * vring is triggered.
241+ * @pa: physical address
242+ *
243+ * This descriptor is not a resource entry by itself; it is part of the
244+ * vdev resource type (see below).
245+ *
246+ * Note that @da should either contain the device address where
247+ * the remote processor is expecting the vring, or indicate that
248+ * dynamically allocation of the vring's device address is supported.
249+ */
250+struct fw_rsc_vdev_vring {
251+ u32 da;
252+ u32 align;
253+ u32 num;
254+ u32 notifyid;
255+ u32 pa;
256+} __packed;
257+
258+/**
259+ * struct fw_rsc_vdev - virtio device header
260+ * @id: virtio device id (as in virtio_ids.h)
261+ * @notifyid: a unique rproc-wide notify index for this vdev. This notify
262+ * index is used when kicking a remote processor, to let it know that the
263+ * status/features of this vdev have changes.
264+ * @dfeatures: specifies the virtio device features supported by the firmware
265+ * @gfeatures: a place holder used by the host to write back the
266+ * negotiated features that are supported by both sides.
267+ * @config_len: the size of the virtio config space of this vdev. The config
268+ * space lies in the resource table immediate after this vdev header.
269+ * @status: a place holder where the host will indicate its virtio progress.
270+ * @num_of_vrings: indicates how many vrings are described in this vdev header
271+ * @reserved: reserved (must be zero)
272+ * @vring: an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'.
273+ *
274+ * This resource is a virtio device header: it provides information about
275+ * the vdev, and is then used by the host and its peer remote processors
276+ * to negotiate and share certain virtio properties.
277+ *
278+ * By providing this resource entry, the firmware essentially asks remoteproc
279+ * to statically allocate a vdev upon registration of the rproc (dynamic vdev
280+ * allocation is not yet supported).
281+ *
282+ * Note:
283+ * 1. unlike virtualization systems, the term 'host' here means
284+ * the Linux side which is running remoteproc to control the remote
285+ * processors. We use the name 'gfeatures' to comply with virtio's terms,
286+ * though there isn't really any virtualized guest OS here: it's the host
287+ * which is responsible for negotiating the final features.
288+ * Yeah, it's a bit confusing.
289+ *
290+ * 2. immediately following this structure is the virtio config space for
291+ * this vdev (which is specific to the vdev; for more info, read the virtio
292+ * spec). The size of the config space is specified by @config_len.
293+ */
294+struct fw_rsc_vdev {
295+ u32 id;
296+ u32 notifyid;
297+ u32 dfeatures;
298+ u32 gfeatures;
299+ u32 config_len;
300+ u8 status;
301+ u8 num_of_vrings;
302+ u8 reserved[2];
303+ struct fw_rsc_vdev_vring vring[];
304+} __packed;
305+
306+/**
307+ * rsc_table_for_each_entry() - iterate over all entries in a resource table
308+ * @table: pointer to the resource table
309+ * @table_sz: total size of the table buffer in bytes
310+ * @dev: device used for error logging
311+ * @cb: callback invoked for each entry:
312+ * @type - value from enum fw_resource_type
313+ * @rsc - pointer to the entry payload (past struct fw_rsc_hdr)
314+ * @offset - byte offset of the payload within the table; callers
315+ * that write back into the table (e.g. to record a
316+ * dynamically allocated address) use this to locate the
317+ * entry for later update
318+ * @avail - bytes available in the payload
319+ * @data - caller-supplied private pointer
320+ * Return 0 to continue iteration, non-zero to stop.
321+ * @data: private pointer forwarded to @cb on every call
322+ *
323+ * Iterates over every resource entry in @table, performing the standard
324+ * truncation check, and invokes @cb for each one. Iteration stops on the
325+ * first non-zero return from @cb or on a malformed table.
326+ *
327+ * Returns 0 after a complete iteration, -EINVAL if the table is truncated,
328+ * or the first non-zero value returned by @cb.
329+ */
330+static inline int rsc_table_for_each_entry(struct resource_table *table,
331+ size_t table_sz,
332+ struct device *dev,
333+ int (*cb)(u32 type, void *rsc,
334+ int offset, int avail,
335+ void *data),
336+ void *data) {
337+ int i, ret;
338+
339+ for (i = 0; i < table->num; i++) {
340+ int offset = table->offset[i];
341+ struct fw_rsc_hdr *hdr = (void *)table + offset;
342+ int avail = table_sz - offset - sizeof(*hdr);
343+ int rsc_offset = offset + sizeof(*hdr);
344+ void *rsc = (void *)hdr + sizeof(*hdr);
345+
346+ if (avail < 0) {
347+ dev_err(dev, "rsc table is truncated\n");
348+ return -EINVAL;
349+ }
350+
351+ ret = cb(hdr->type, rsc, rsc_offset, avail, data);
352+ if (ret)
353+ return ret;
354+ }
355+
356+ return 0;
357+}
358+
359+#endif /* RSC_TABLE_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t