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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'qcom-drivers-for-6.20' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into soc/drivers

Qualcomm driver updates for v6.20

Support multiple wait queues in the SCM firmware interface and provide
discovery of the wait queue interrupt to deal with the cases where
bootloader didn't patch the DeviceTree with the IRQ information.

Refactor the MDT loader and the SCM driver's peripheral authentication
service interface and introduce support for passing a remoteproc
resource table to the firmware. The remoteproc patches that uses this
and uses this to configure the IOMMU are included here due to
bidirectional dependencies. The end result is remoteproc support on the
Glymur platform.

Enable QSEECOM and thereby UEFI variable access, on the Surface Pro 11.

Make the QMI interface endianness aware, to support ath1Xk on big endian
machines.

Add the Glymur support in LLCC driver.

* tag 'qcom-drivers-for-6.20' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux: (33 commits)
soc: qcom: preserve CPU endianness for QMI_DATA_LEN
soc: qcom: fix QMI encoding/decoding for basic elements
soc: qcom: check QMI basic element error codes
soc: qcom: ubwc: add missing include
remoteproc: qcom: pas: Enable Secure PAS support with IOMMU managed by Linux
remoteproc: pas: Extend parse_fw callback to fetch resources via SMC call
firmware: qcom_scm: Add qcom_scm_pas_get_rsc_table() to get resource table
firmware: qcom_scm: Add SHM bridge handling for PAS when running without QHEE
firmware: qcom_scm: Refactor qcom_scm_pas_init_image()
firmware: qcom_scm: Add a prep version of auth_and_reset function
soc: qcom: mdtloader: Remove qcom_mdt_pas_init() from exported symbols
soc: qcom: mdtloader: Add PAS context aware qcom_mdt_pas_load() function
remoteproc: pas: Replace metadata context with PAS context structure
firmware: qcom_scm: Introduce PAS context allocator helper function
firmware: qcom_scm: Rename peripheral as pas_id
firmware: qcom_scm: Remove redundant piece of code
dt-bindings: remoteproc: qcom,pas: Add iommus property
soc: qcom: cmd-db: Use devm_memremap() to fix memory leak in cmd_db_dev_probe
soc: qcom: pmic_glink_altmode: Consume TBT3/USB4 mode notifications
dt-bindings: qcom,pdc: document the Milos Power Domain Controller
...

Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+1199 -189
+44 -2
Documentation/devicetree/bindings/cache/qcom,llcc.yaml
··· 20 20 properties: 21 21 compatible: 22 22 enum: 23 + - qcom,glymur-llcc 23 24 - qcom,ipq5424-llcc 24 25 - qcom,kaanapali-llcc 25 26 - qcom,qcs615-llcc ··· 47 46 48 47 reg: 49 48 minItems: 1 50 - maxItems: 10 49 + maxItems: 14 51 50 52 51 reg-names: 53 52 minItems: 1 54 - maxItems: 10 53 + maxItems: 14 55 54 56 55 interrupts: 57 56 maxItems: 1 ··· 84 83 reg-names: 85 84 items: 86 85 - const: llcc0_base 86 + 87 + - if: 88 + properties: 89 + compatible: 90 + contains: 91 + enum: 92 + - qcom,glymur-llcc 93 + then: 94 + properties: 95 + reg: 96 + items: 97 + - description: LLCC0 base register region 98 + - description: LLCC1 base register region 99 + - description: LLCC2 base register region 100 + - description: LLCC3 base register region 101 + - description: LLCC4 base register region 102 + - description: LLCC5 base register region 103 + - description: LLCC6 base register region 104 + - description: LLCC7 base register region 105 + - description: LLCC8 base register region 106 + - description: LLCC9 base register region 107 + - description: LLCC10 base register region 108 + - description: LLCC11 base register region 109 + - description: LLCC broadcast base register region 110 + - description: LLCC broadcast AND register region 111 + reg-names: 112 + items: 113 + - const: llcc0_base 114 + - const: llcc1_base 115 + - const: llcc2_base 116 + - const: llcc3_base 117 + - const: llcc4_base 118 + - const: llcc5_base 119 + - const: llcc6_base 120 + - const: llcc7_base 121 + - const: llcc8_base 122 + - const: llcc9_base 123 + - const: llcc10_base 124 + - const: llcc11_base 125 + - const: llcc_broadcast_base 126 + - const: llcc_broadcast_and_base 87 127 88 128 - if: 89 129 properties:
+1
Documentation/devicetree/bindings/crypto/qcom,prng.yaml
··· 21 21 - qcom,ipq5424-trng 22 22 - qcom,ipq9574-trng 23 23 - qcom,kaanapali-trng 24 + - qcom,milos-trng 24 25 - qcom,qcs615-trng 25 26 - qcom,qcs8300-trng 26 27 - qcom,sa8255p-trng
+2
Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml
··· 27 27 items: 28 28 - enum: 29 29 - qcom,glymur-pdc 30 + - qcom,kaanapali-pdc 31 + - qcom,milos-pdc 30 32 - qcom,qcs615-pdc 31 33 - qcom,qcs8300-pdc 32 34 - qcom,qdu1000-pdc
+3
Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml
··· 44 44 - const: stop-ack 45 45 - const: shutdown-ack 46 46 47 + iommus: 48 + maxItems: 1 49 + 47 50 power-domains: 48 51 minItems: 1 49 52 maxItems: 3
+2
Documentation/devicetree/bindings/sram/sram.yaml
··· 34 34 - nvidia,tegra186-sysram 35 35 - nvidia,tegra194-sysram 36 36 - nvidia,tegra234-sysram 37 + - qcom,kaanapali-imem 37 38 - qcom,rpm-msg-ram 38 39 - rockchip,rk3288-pmu-sram 39 40 ··· 90 89 - arm,juno-scp-shmem 91 90 - arm,scmi-shmem 92 91 - arm,scp-shmem 92 + - qcom,pil-reloc-info 93 93 - renesas,smp-sram 94 94 - rockchip,rk3066-smp-sram 95 95 - samsung,exynos4210-sysram
+2 -5
drivers/bus/qcom-ebi2.c
··· 292 292 static int qcom_ebi2_probe(struct platform_device *pdev) 293 293 { 294 294 struct device_node *np = pdev->dev.of_node; 295 - struct device_node *child; 296 295 struct device *dev = &pdev->dev; 297 296 struct resource *res; 298 297 void __iomem *ebi2_base; ··· 347 348 writel(val, ebi2_base); 348 349 349 350 /* Walk over the child nodes and see what chipselects we use */ 350 - for_each_available_child_of_node(np, child) { 351 + for_each_available_child_of_node_scoped(np, child) { 351 352 u32 csindex; 352 353 353 354 /* Figure out the chipselect */ 354 355 ret = of_property_read_u32(child, "reg", &csindex); 355 - if (ret) { 356 - of_node_put(child); 356 + if (ret) 357 357 return ret; 358 - } 359 358 360 359 if (csindex > 5) { 361 360 dev_err(dev,
+1 -1
drivers/clk/qcom/common.c
··· 454 454 455 455 base = devm_platform_ioremap_resource(pdev, index); 456 456 if (IS_ERR(base)) 457 - return -ENOMEM; 457 + return PTR_ERR(base); 458 458 459 459 regmap = devm_regmap_init_mmio(&pdev->dev, base, desc->config); 460 460 if (IS_ERR(regmap))
+442 -65
drivers/firmware/qcom/qcom_scm.c
··· 27 27 #include <linux/of_reserved_mem.h> 28 28 #include <linux/platform_device.h> 29 29 #include <linux/reset-controller.h> 30 + #include <linux/remoteproc.h> 30 31 #include <linux/sizes.h> 31 32 #include <linux/types.h> 33 + 34 + #include <dt-bindings/interrupt-controller/arm-gic.h> 32 35 33 36 #include "qcom_scm.h" 34 37 #include "qcom_tzmem.h" 35 38 36 39 static u32 download_mode; 40 + 41 + #define GIC_SPI_BASE 32 42 + #define GIC_MAX_SPI 1019 // SPIs in GICv3 spec range from 32..1019 43 + #define GIC_ESPI_BASE 4096 44 + #define GIC_MAX_ESPI 5119 // ESPIs in GICv3 spec range from 4096..5119 37 45 38 46 struct qcom_scm { 39 47 struct device *dev; ··· 49 41 struct clk *iface_clk; 50 42 struct clk *bus_clk; 51 43 struct icc_path *path; 52 - struct completion waitq_comp; 44 + struct completion *waitq_comps; 53 45 struct reset_controller_dev reset; 54 46 55 47 /* control access to the interconnect path */ ··· 59 51 u64 dload_mode_addr; 60 52 61 53 struct qcom_tzmem_pool *mempool; 54 + unsigned int wq_cnt; 62 55 }; 63 56 64 57 struct qcom_scm_current_perm_info { ··· 120 111 QSEECOM_TZ_CMD_INFO_VERSION = 3, 121 112 }; 122 113 114 + #define RSCTABLE_BUFFER_NOT_SUFFICIENT 20 115 + 123 116 #define QSEECOM_MAX_APP_NAME_SIZE 64 124 117 #define SHMBRIDGE_RESULT_NOTSUPP 4 125 118 ··· 140 129 #define QCOM_DLOAD_FULLDUMP 1 141 130 #define QCOM_DLOAD_MINIDUMP 2 142 131 #define QCOM_DLOAD_BOTHDUMP 3 132 + 133 + #define QCOM_SCM_DEFAULT_WAITQ_COUNT 1 143 134 144 135 static const char * const qcom_scm_convention_names[] = { 145 136 [SMC_CONVENTION_UNKNOWN] = "unknown", ··· 572 559 } 573 560 574 561 /** 562 + * devm_qcom_scm_pas_context_alloc() - Allocate peripheral authentication service 563 + * context for a given peripheral 564 + * 565 + * PAS context is device-resource managed, so the caller does not need 566 + * to worry about freeing the context memory. 567 + * 568 + * @dev: PAS firmware device 569 + * @pas_id: peripheral authentication service id 570 + * @mem_phys: Subsystem reserve memory start address 571 + * @mem_size: Subsystem reserve memory size 572 + * 573 + * Returns: The new PAS context, or ERR_PTR() on failure. 574 + */ 575 + struct qcom_scm_pas_context *devm_qcom_scm_pas_context_alloc(struct device *dev, 576 + u32 pas_id, 577 + phys_addr_t mem_phys, 578 + size_t mem_size) 579 + { 580 + struct qcom_scm_pas_context *ctx; 581 + 582 + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 583 + if (!ctx) 584 + return ERR_PTR(-ENOMEM); 585 + 586 + ctx->dev = dev; 587 + ctx->pas_id = pas_id; 588 + ctx->mem_phys = mem_phys; 589 + ctx->mem_size = mem_size; 590 + 591 + return ctx; 592 + } 593 + EXPORT_SYMBOL_GPL(devm_qcom_scm_pas_context_alloc); 594 + 595 + static int __qcom_scm_pas_init_image(u32 pas_id, dma_addr_t mdata_phys, 596 + struct qcom_scm_res *res) 597 + { 598 + struct qcom_scm_desc desc = { 599 + .svc = QCOM_SCM_SVC_PIL, 600 + .cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE, 601 + .arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW), 602 + .args[0] = pas_id, 603 + .owner = ARM_SMCCC_OWNER_SIP, 604 + }; 605 + int ret; 606 + 607 + ret = qcom_scm_clk_enable(); 608 + if (ret) 609 + return ret; 610 + 611 + ret = qcom_scm_bw_enable(); 612 + if (ret) 613 + goto disable_clk; 614 + 615 + desc.args[1] = mdata_phys; 616 + 617 + ret = qcom_scm_call(__scm->dev, &desc, res); 618 + qcom_scm_bw_disable(); 619 + 620 + disable_clk: 621 + qcom_scm_clk_disable(); 622 + 623 + return ret; 624 + } 625 + 626 + static int qcom_scm_pas_prep_and_init_image(struct qcom_scm_pas_context *ctx, 627 + const void *metadata, size_t size) 628 + { 629 + struct qcom_scm_res res; 630 + phys_addr_t mdata_phys; 631 + void *mdata_buf; 632 + int ret; 633 + 634 + mdata_buf = qcom_tzmem_alloc(__scm->mempool, size, GFP_KERNEL); 635 + if (!mdata_buf) 636 + return -ENOMEM; 637 + 638 + memcpy(mdata_buf, metadata, size); 639 + mdata_phys = qcom_tzmem_to_phys(mdata_buf); 640 + 641 + ret = __qcom_scm_pas_init_image(ctx->pas_id, mdata_phys, &res); 642 + if (ret < 0) 643 + qcom_tzmem_free(mdata_buf); 644 + else 645 + ctx->ptr = mdata_buf; 646 + 647 + return ret ? : res.result[0]; 648 + } 649 + 650 + /** 575 651 * qcom_scm_pas_init_image() - Initialize peripheral authentication service 576 652 * state machine for a given peripheral, using the 577 653 * metadata 578 - * @peripheral: peripheral id 654 + * @pas_id: peripheral authentication service id 579 655 * @metadata: pointer to memory containing ELF header, program header table 580 656 * and optional blob of data used for authenticating the metadata 581 657 * and the rest of the firmware 582 658 * @size: size of the metadata 583 - * @ctx: optional metadata context 659 + * @ctx: optional pas context 584 660 * 585 661 * Return: 0 on success. 586 662 * ··· 677 575 * track the metadata allocation, this needs to be released by invoking 678 576 * qcom_scm_pas_metadata_release() by the caller. 679 577 */ 680 - int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size, 681 - struct qcom_scm_pas_metadata *ctx) 578 + int qcom_scm_pas_init_image(u32 pas_id, const void *metadata, size_t size, 579 + struct qcom_scm_pas_context *ctx) 682 580 { 581 + struct qcom_scm_res res; 683 582 dma_addr_t mdata_phys; 684 583 void *mdata_buf; 685 584 int ret; 686 - struct qcom_scm_desc desc = { 687 - .svc = QCOM_SCM_SVC_PIL, 688 - .cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE, 689 - .arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW), 690 - .args[0] = peripheral, 691 - .owner = ARM_SMCCC_OWNER_SIP, 692 - }; 693 - struct qcom_scm_res res; 585 + 586 + if (ctx && ctx->use_tzmem) 587 + return qcom_scm_pas_prep_and_init_image(ctx, metadata, size); 694 588 695 589 /* 696 590 * During the scm call memory protection will be enabled for the meta ··· 707 609 708 610 memcpy(mdata_buf, metadata, size); 709 611 710 - ret = qcom_scm_clk_enable(); 711 - if (ret) 712 - goto out; 713 - 714 - ret = qcom_scm_bw_enable(); 715 - if (ret) 716 - goto disable_clk; 717 - 718 - desc.args[1] = mdata_phys; 719 - 720 - ret = qcom_scm_call(__scm->dev, &desc, &res); 721 - qcom_scm_bw_disable(); 722 - 723 - disable_clk: 724 - qcom_scm_clk_disable(); 725 - 726 - out: 612 + ret = __qcom_scm_pas_init_image(pas_id, mdata_phys, &res); 727 613 if (ret < 0 || !ctx) { 728 614 dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys); 729 615 } else if (ctx) { ··· 722 640 723 641 /** 724 642 * qcom_scm_pas_metadata_release() - release metadata context 725 - * @ctx: metadata context 643 + * @ctx: pas context 726 644 */ 727 - void qcom_scm_pas_metadata_release(struct qcom_scm_pas_metadata *ctx) 645 + void qcom_scm_pas_metadata_release(struct qcom_scm_pas_context *ctx) 728 646 { 729 647 if (!ctx->ptr) 730 648 return; 731 649 732 - dma_free_coherent(__scm->dev, ctx->size, ctx->ptr, ctx->phys); 650 + if (ctx->use_tzmem) 651 + qcom_tzmem_free(ctx->ptr); 652 + else 653 + dma_free_coherent(__scm->dev, ctx->size, ctx->ptr, ctx->phys); 733 654 734 655 ctx->ptr = NULL; 735 - ctx->phys = 0; 736 - ctx->size = 0; 737 656 } 738 657 EXPORT_SYMBOL_GPL(qcom_scm_pas_metadata_release); 739 658 740 659 /** 741 660 * qcom_scm_pas_mem_setup() - Prepare the memory related to a given peripheral 742 661 * for firmware loading 743 - * @peripheral: peripheral id 662 + * @pas_id: peripheral authentication service id 744 663 * @addr: start address of memory area to prepare 745 664 * @size: size of the memory area to prepare 746 665 * 747 666 * Returns 0 on success. 748 667 */ 749 - int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size) 668 + int qcom_scm_pas_mem_setup(u32 pas_id, phys_addr_t addr, phys_addr_t size) 750 669 { 751 670 int ret; 752 671 struct qcom_scm_desc desc = { 753 672 .svc = QCOM_SCM_SVC_PIL, 754 673 .cmd = QCOM_SCM_PIL_PAS_MEM_SETUP, 755 674 .arginfo = QCOM_SCM_ARGS(3), 756 - .args[0] = peripheral, 675 + .args[0] = pas_id, 757 676 .args[1] = addr, 758 677 .args[2] = size, 759 678 .owner = ARM_SMCCC_OWNER_SIP, ··· 779 696 } 780 697 EXPORT_SYMBOL_GPL(qcom_scm_pas_mem_setup); 781 698 699 + static void *__qcom_scm_pas_get_rsc_table(u32 pas_id, void *input_rt_tzm, 700 + size_t input_rt_size, 701 + size_t *output_rt_size) 702 + { 703 + struct qcom_scm_desc desc = { 704 + .svc = QCOM_SCM_SVC_PIL, 705 + .cmd = QCOM_SCM_PIL_PAS_GET_RSCTABLE, 706 + .arginfo = QCOM_SCM_ARGS(5, QCOM_SCM_VAL, QCOM_SCM_RO, QCOM_SCM_VAL, 707 + QCOM_SCM_RW, QCOM_SCM_VAL), 708 + .args[0] = pas_id, 709 + .owner = ARM_SMCCC_OWNER_SIP, 710 + }; 711 + struct qcom_scm_res res; 712 + void *output_rt_tzm; 713 + int ret; 714 + 715 + output_rt_tzm = qcom_tzmem_alloc(__scm->mempool, *output_rt_size, GFP_KERNEL); 716 + if (!output_rt_tzm) 717 + return ERR_PTR(-ENOMEM); 718 + 719 + desc.args[1] = qcom_tzmem_to_phys(input_rt_tzm); 720 + desc.args[2] = input_rt_size; 721 + desc.args[3] = qcom_tzmem_to_phys(output_rt_tzm); 722 + desc.args[4] = *output_rt_size; 723 + 724 + /* 725 + * Whether SMC fail or pass, res.result[2] will hold actual resource table 726 + * size. 727 + * 728 + * If passed 'output_rt_size' buffer size is not sufficient to hold the 729 + * resource table TrustZone sends, response code in res.result[1] as 730 + * RSCTABLE_BUFFER_NOT_SUFFICIENT so that caller can retry this SMC call 731 + * with output_rt_tzm buffer with res.result[2] size however, It should not 732 + * be of unresonable size. 733 + */ 734 + ret = qcom_scm_call(__scm->dev, &desc, &res); 735 + if (!ret && res.result[2] > SZ_1G) { 736 + ret = -E2BIG; 737 + goto free_output_rt; 738 + } 739 + 740 + *output_rt_size = res.result[2]; 741 + if (ret && res.result[1] == RSCTABLE_BUFFER_NOT_SUFFICIENT) 742 + ret = -EOVERFLOW; 743 + 744 + free_output_rt: 745 + if (ret) 746 + qcom_tzmem_free(output_rt_tzm); 747 + 748 + return ret ? ERR_PTR(ret) : output_rt_tzm; 749 + } 750 + 751 + /** 752 + * qcom_scm_pas_get_rsc_table() - Retrieve the resource table in passed output buffer 753 + * for a given peripheral. 754 + * 755 + * Qualcomm remote processor may rely on both static and dynamic resources for 756 + * its functionality. Static resources typically refer to memory-mapped addresses 757 + * required by the subsystem and are often embedded within the firmware binary 758 + * and dynamic resources, such as shared memory in DDR etc., are determined at 759 + * runtime during the boot process. 760 + * 761 + * On Qualcomm Technologies devices, it's possible that static resources are not 762 + * embedded in the firmware binary and instead are provided by TrustZone However, 763 + * dynamic resources are always expected to come from TrustZone. This indicates 764 + * that for Qualcomm devices, all resources (static and dynamic) will be provided 765 + * by TrustZone via the SMC call. 766 + * 767 + * If the remote processor firmware binary does contain static resources, they 768 + * should be passed in input_rt. These will be forwarded to TrustZone for 769 + * authentication. TrustZone will then append the dynamic resources and return 770 + * the complete resource table in output_rt_tzm. 771 + * 772 + * If the remote processor firmware binary does not include a resource table, 773 + * the caller of this function should set input_rt as NULL and input_rt_size 774 + * as zero respectively. 775 + * 776 + * More about documentation on resource table data structures can be found in 777 + * include/linux/remoteproc.h 778 + * 779 + * @ctx: PAS context 780 + * @pas_id: peripheral authentication service id 781 + * @input_rt: resource table buffer which is present in firmware binary 782 + * @input_rt_size: size of the resource table present in firmware binary 783 + * @output_rt_size: TrustZone expects caller should pass worst case size for 784 + * the output_rt_tzm. 785 + * 786 + * Return: 787 + * On success, returns a pointer to the allocated buffer containing the final 788 + * resource table and output_rt_size will have actual resource table size from 789 + * TrustZone. The caller is responsible for freeing the buffer. On failure, 790 + * returns ERR_PTR(-errno). 791 + */ 792 + struct resource_table *qcom_scm_pas_get_rsc_table(struct qcom_scm_pas_context *ctx, 793 + void *input_rt, 794 + size_t input_rt_size, 795 + size_t *output_rt_size) 796 + { 797 + struct resource_table empty_rsc = {}; 798 + size_t size = SZ_16K; 799 + void *output_rt_tzm; 800 + void *input_rt_tzm; 801 + void *tbl_ptr; 802 + int ret; 803 + 804 + ret = qcom_scm_clk_enable(); 805 + if (ret) 806 + return ERR_PTR(ret); 807 + 808 + ret = qcom_scm_bw_enable(); 809 + if (ret) 810 + goto disable_clk; 811 + 812 + /* 813 + * TrustZone can not accept buffer as NULL value as argument hence, 814 + * we need to pass a input buffer indicating that subsystem firmware 815 + * does not have resource table by filling resource table structure. 816 + */ 817 + if (!input_rt) { 818 + input_rt = &empty_rsc; 819 + input_rt_size = sizeof(empty_rsc); 820 + } 821 + 822 + input_rt_tzm = qcom_tzmem_alloc(__scm->mempool, input_rt_size, GFP_KERNEL); 823 + if (!input_rt_tzm) { 824 + ret = -ENOMEM; 825 + goto disable_scm_bw; 826 + } 827 + 828 + memcpy(input_rt_tzm, input_rt, input_rt_size); 829 + 830 + output_rt_tzm = __qcom_scm_pas_get_rsc_table(ctx->pas_id, input_rt_tzm, 831 + input_rt_size, &size); 832 + if (PTR_ERR(output_rt_tzm) == -EOVERFLOW) 833 + /* Try again with the size requested by the TZ */ 834 + output_rt_tzm = __qcom_scm_pas_get_rsc_table(ctx->pas_id, 835 + input_rt_tzm, 836 + input_rt_size, 837 + &size); 838 + if (IS_ERR(output_rt_tzm)) { 839 + ret = PTR_ERR(output_rt_tzm); 840 + goto free_input_rt; 841 + } 842 + 843 + tbl_ptr = kzalloc(size, GFP_KERNEL); 844 + if (!tbl_ptr) { 845 + qcom_tzmem_free(output_rt_tzm); 846 + ret = -ENOMEM; 847 + goto free_input_rt; 848 + } 849 + 850 + memcpy(tbl_ptr, output_rt_tzm, size); 851 + *output_rt_size = size; 852 + qcom_tzmem_free(output_rt_tzm); 853 + 854 + free_input_rt: 855 + qcom_tzmem_free(input_rt_tzm); 856 + 857 + disable_scm_bw: 858 + qcom_scm_bw_disable(); 859 + 860 + disable_clk: 861 + qcom_scm_clk_disable(); 862 + 863 + return ret ? ERR_PTR(ret) : tbl_ptr; 864 + } 865 + EXPORT_SYMBOL_GPL(qcom_scm_pas_get_rsc_table); 866 + 782 867 /** 783 868 * qcom_scm_pas_auth_and_reset() - Authenticate the given peripheral firmware 784 869 * and reset the remote processor 785 - * @peripheral: peripheral id 870 + * @pas_id: peripheral authentication service id 786 871 * 787 872 * Return 0 on success. 788 873 */ 789 - int qcom_scm_pas_auth_and_reset(u32 peripheral) 874 + int qcom_scm_pas_auth_and_reset(u32 pas_id) 790 875 { 791 876 int ret; 792 877 struct qcom_scm_desc desc = { 793 878 .svc = QCOM_SCM_SVC_PIL, 794 879 .cmd = QCOM_SCM_PIL_PAS_AUTH_AND_RESET, 795 880 .arginfo = QCOM_SCM_ARGS(1), 796 - .args[0] = peripheral, 881 + .args[0] = pas_id, 797 882 .owner = ARM_SMCCC_OWNER_SIP, 798 883 }; 799 884 struct qcom_scm_res res; ··· 985 734 EXPORT_SYMBOL_GPL(qcom_scm_pas_auth_and_reset); 986 735 987 736 /** 737 + * qcom_scm_pas_prepare_and_auth_reset() - Prepare, authenticate, and reset the 738 + * remote processor 739 + * 740 + * @ctx: Context saved during call to qcom_scm_pas_context_init() 741 + * 742 + * This function performs the necessary steps to prepare a PAS subsystem, 743 + * authenticate it using the provided metadata, and initiate a reset sequence. 744 + * 745 + * It should be used when Linux is in control setting up the IOMMU hardware 746 + * for remote subsystem during secure firmware loading processes. The preparation 747 + * step sets up a shmbridge over the firmware memory before TrustZone accesses the 748 + * firmware memory region for authentication. The authentication step verifies 749 + * the integrity and authenticity of the firmware or configuration using secure 750 + * metadata. Finally, the reset step ensures the subsystem starts in a clean and 751 + * sane state. 752 + * 753 + * Return: 0 on success, negative errno on failure. 754 + */ 755 + int qcom_scm_pas_prepare_and_auth_reset(struct qcom_scm_pas_context *ctx) 756 + { 757 + u64 handle; 758 + int ret; 759 + 760 + /* 761 + * When Linux running @ EL1, Gunyah hypervisor running @ EL2 traps the 762 + * auth_and_reset call and create an shmbridge on the remote subsystem 763 + * memory region and then invokes a call to TrustZone to authenticate. 764 + */ 765 + if (!ctx->use_tzmem) 766 + return qcom_scm_pas_auth_and_reset(ctx->pas_id); 767 + 768 + /* 769 + * When Linux runs @ EL2 Linux must create the shmbridge itself and then 770 + * subsequently call TrustZone for authenticate and reset. 771 + */ 772 + ret = qcom_tzmem_shm_bridge_create(ctx->mem_phys, ctx->mem_size, &handle); 773 + if (ret) 774 + return ret; 775 + 776 + ret = qcom_scm_pas_auth_and_reset(ctx->pas_id); 777 + qcom_tzmem_shm_bridge_delete(handle); 778 + 779 + return ret; 780 + } 781 + EXPORT_SYMBOL_GPL(qcom_scm_pas_prepare_and_auth_reset); 782 + 783 + /** 988 784 * qcom_scm_pas_shutdown() - Shut down the remote processor 989 - * @peripheral: peripheral id 785 + * @pas_id: peripheral authentication service id 990 786 * 991 787 * Returns 0 on success. 992 788 */ 993 - int qcom_scm_pas_shutdown(u32 peripheral) 789 + int qcom_scm_pas_shutdown(u32 pas_id) 994 790 { 995 791 int ret; 996 792 struct qcom_scm_desc desc = { 997 793 .svc = QCOM_SCM_SVC_PIL, 998 794 .cmd = QCOM_SCM_PIL_PAS_SHUTDOWN, 999 795 .arginfo = QCOM_SCM_ARGS(1), 1000 - .args[0] = peripheral, 796 + .args[0] = pas_id, 1001 797 .owner = ARM_SMCCC_OWNER_SIP, 1002 798 }; 1003 799 struct qcom_scm_res res; ··· 1070 772 /** 1071 773 * qcom_scm_pas_supported() - Check if the peripheral authentication service is 1072 774 * available for the given peripherial 1073 - * @peripheral: peripheral id 775 + * @pas_id: peripheral authentication service id 1074 776 * 1075 777 * Returns true if PAS is supported for this peripheral, otherwise false. 1076 778 */ 1077 - bool qcom_scm_pas_supported(u32 peripheral) 779 + bool qcom_scm_pas_supported(u32 pas_id) 1078 780 { 1079 781 int ret; 1080 782 struct qcom_scm_desc desc = { 1081 783 .svc = QCOM_SCM_SVC_PIL, 1082 784 .cmd = QCOM_SCM_PIL_PAS_IS_SUPPORTED, 1083 785 .arginfo = QCOM_SCM_ARGS(1), 1084 - .args[0] = peripheral, 786 + .args[0] = pas_id, 1085 787 .owner = ARM_SMCCC_OWNER_SIP, 1086 788 }; 1087 789 struct qcom_scm_res res; ··· 2305 2007 { .compatible = "lenovo,yoga-slim7x" }, 2306 2008 { .compatible = "microsoft,arcata", }, 2307 2009 { .compatible = "microsoft,blackrock" }, 2010 + { .compatible = "microsoft,denali", }, 2308 2011 { .compatible = "microsoft,romulus13", }, 2309 2012 { .compatible = "microsoft,romulus15", }, 2310 2013 { .compatible = "qcom,hamoa-iot-evk" }, ··· 2507 2208 } 2508 2209 EXPORT_SYMBOL_GPL(qcom_scm_is_available); 2509 2210 2510 - static int qcom_scm_assert_valid_wq_ctx(u32 wq_ctx) 2211 + static int qcom_scm_fill_irq_fwspec_params(struct irq_fwspec *fwspec, u32 hwirq) 2511 2212 { 2512 - /* FW currently only supports a single wq_ctx (zero). 2513 - * TODO: Update this logic to include dynamic allocation and lookup of 2514 - * completion structs when FW supports more wq_ctx values. 2515 - */ 2516 - if (wq_ctx != 0) { 2517 - dev_err(__scm->dev, "Firmware unexpectedly passed non-zero wq_ctx\n"); 2518 - return -EINVAL; 2213 + if (hwirq >= GIC_SPI_BASE && hwirq <= GIC_MAX_SPI) { 2214 + fwspec->param[0] = GIC_SPI; 2215 + fwspec->param[1] = hwirq - GIC_SPI_BASE; 2216 + } else if (hwirq >= GIC_ESPI_BASE && hwirq <= GIC_MAX_ESPI) { 2217 + fwspec->param[0] = GIC_ESPI; 2218 + fwspec->param[1] = hwirq - GIC_ESPI_BASE; 2219 + } else { 2220 + WARN(1, "Unexpected hwirq: %d\n", hwirq); 2221 + return -ENXIO; 2519 2222 } 2223 + 2224 + fwspec->param[2] = IRQ_TYPE_EDGE_RISING; 2225 + fwspec->param_count = 3; 2520 2226 2521 2227 return 0; 2522 2228 } 2523 2229 2524 - int qcom_scm_wait_for_wq_completion(u32 wq_ctx) 2230 + static int qcom_scm_query_waitq_count(struct qcom_scm *scm) 2525 2231 { 2232 + struct qcom_scm_desc desc = { 2233 + .svc = QCOM_SCM_SVC_WAITQ, 2234 + .cmd = QCOM_SCM_WAITQ_GET_INFO, 2235 + .owner = ARM_SMCCC_OWNER_SIP 2236 + }; 2237 + struct qcom_scm_res res; 2526 2238 int ret; 2527 2239 2528 - ret = qcom_scm_assert_valid_wq_ctx(wq_ctx); 2240 + ret = qcom_scm_call_atomic(scm->dev, &desc, &res); 2529 2241 if (ret) 2530 2242 return ret; 2531 2243 2532 - wait_for_completion(&__scm->waitq_comp); 2244 + return res.result[0] & GENMASK(7, 0); 2245 + } 2246 + 2247 + static int qcom_scm_get_waitq_irq(struct qcom_scm *scm) 2248 + { 2249 + struct qcom_scm_desc desc = { 2250 + .svc = QCOM_SCM_SVC_WAITQ, 2251 + .cmd = QCOM_SCM_WAITQ_GET_INFO, 2252 + .owner = ARM_SMCCC_OWNER_SIP 2253 + }; 2254 + struct device_node *parent_irq_node; 2255 + struct irq_fwspec fwspec; 2256 + struct qcom_scm_res res; 2257 + u32 hwirq; 2258 + int ret; 2259 + 2260 + ret = qcom_scm_call_atomic(scm->dev, &desc, &res); 2261 + if (ret) 2262 + return ret; 2263 + 2264 + hwirq = res.result[1] & GENMASK(15, 0); 2265 + ret = qcom_scm_fill_irq_fwspec_params(&fwspec, hwirq); 2266 + if (ret) 2267 + return ret; 2268 + 2269 + parent_irq_node = of_irq_find_parent(scm->dev->of_node); 2270 + if (!parent_irq_node) 2271 + return -ENODEV; 2272 + 2273 + fwspec.fwnode = of_fwnode_handle(parent_irq_node); 2274 + 2275 + return irq_create_fwspec_mapping(&fwspec); 2276 + } 2277 + 2278 + static struct completion *qcom_scm_get_completion(u32 wq_ctx) 2279 + { 2280 + struct completion *wq; 2281 + 2282 + if (WARN_ON_ONCE(wq_ctx >= __scm->wq_cnt)) 2283 + return ERR_PTR(-EINVAL); 2284 + 2285 + wq = &__scm->waitq_comps[wq_ctx]; 2286 + 2287 + return wq; 2288 + } 2289 + 2290 + int qcom_scm_wait_for_wq_completion(u32 wq_ctx) 2291 + { 2292 + struct completion *wq; 2293 + 2294 + wq = qcom_scm_get_completion(wq_ctx); 2295 + if (IS_ERR(wq)) 2296 + return PTR_ERR(wq); 2297 + 2298 + wait_for_completion_state(wq, TASK_IDLE); 2533 2299 2534 2300 return 0; 2535 2301 } 2536 2302 2537 2303 static int qcom_scm_waitq_wakeup(unsigned int wq_ctx) 2538 2304 { 2539 - int ret; 2305 + struct completion *wq; 2540 2306 2541 - ret = qcom_scm_assert_valid_wq_ctx(wq_ctx); 2542 - if (ret) 2543 - return ret; 2307 + wq = qcom_scm_get_completion(wq_ctx); 2308 + if (IS_ERR(wq)) 2309 + return PTR_ERR(wq); 2544 2310 2545 - complete(&__scm->waitq_comp); 2311 + complete(wq); 2546 2312 2547 2313 return 0; 2548 2314 } ··· 2683 2319 struct qcom_tzmem_pool_config pool_config; 2684 2320 struct qcom_scm *scm; 2685 2321 int irq, ret; 2322 + int i; 2686 2323 2687 2324 scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL); 2688 2325 if (!scm) ··· 2694 2329 if (ret < 0) 2695 2330 return ret; 2696 2331 2697 - init_completion(&scm->waitq_comp); 2698 2332 mutex_init(&scm->scm_bw_lock); 2699 2333 2700 2334 scm->path = devm_of_icc_get(&pdev->dev, NULL); ··· 2745 2381 return dev_err_probe(scm->dev, PTR_ERR(scm->mempool), 2746 2382 "Failed to create the SCM memory pool\n"); 2747 2383 2748 - irq = platform_get_irq_optional(pdev, 0); 2384 + ret = qcom_scm_query_waitq_count(scm); 2385 + scm->wq_cnt = ret < 0 ? QCOM_SCM_DEFAULT_WAITQ_COUNT : ret; 2386 + scm->waitq_comps = devm_kcalloc(&pdev->dev, scm->wq_cnt, sizeof(*scm->waitq_comps), 2387 + GFP_KERNEL); 2388 + if (!scm->waitq_comps) 2389 + return -ENOMEM; 2390 + 2391 + for (i = 0; i < scm->wq_cnt; i++) 2392 + init_completion(&scm->waitq_comps[i]); 2393 + 2394 + irq = qcom_scm_get_waitq_irq(scm); 2395 + if (irq < 0) 2396 + irq = platform_get_irq_optional(pdev, 0); 2397 + 2749 2398 if (irq < 0) { 2750 2399 if (irq != -ENXIO) 2751 2400 return irq;
+2
drivers/firmware/qcom/qcom_scm.h
··· 105 105 #define QCOM_SCM_PIL_PAS_SHUTDOWN 0x06 106 106 #define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07 107 107 #define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a 108 + #define QCOM_SCM_PIL_PAS_GET_RSCTABLE 0x21 108 109 109 110 #define QCOM_SCM_SVC_IO 0x05 110 111 #define QCOM_SCM_IO_READ 0x01 ··· 153 152 #define QCOM_SCM_SVC_WAITQ 0x24 154 153 #define QCOM_SCM_WAITQ_RESUME 0x02 155 154 #define QCOM_SCM_WAITQ_GET_WQ_CTX 0x03 155 + #define QCOM_SCM_WAITQ_GET_INFO 0x04 156 156 157 157 #define QCOM_SCM_SVC_GPU 0x28 158 158 #define QCOM_SCM_SVC_GPU_INIT_REGS 0x01
+130 -35
drivers/remoteproc/qcom_q6v5_pas.c
··· 11 11 #include <linux/delay.h> 12 12 #include <linux/firmware.h> 13 13 #include <linux/interrupt.h> 14 + #include <linux/iommu.h> 14 15 #include <linux/kernel.h> 15 16 #include <linux/module.h> 16 17 #include <linux/of.h> ··· 118 117 struct qcom_rproc_ssr ssr_subdev; 119 118 struct qcom_sysmon *sysmon; 120 119 121 - struct qcom_scm_pas_metadata pas_metadata; 122 - struct qcom_scm_pas_metadata dtb_pas_metadata; 120 + struct qcom_scm_pas_context *pas_ctx; 121 + struct qcom_scm_pas_context *dtb_pas_ctx; 123 122 }; 124 123 125 124 static void qcom_pas_segment_dump(struct rproc *rproc, ··· 212 211 * auth_and_reset() was successful, but in other cases clean it up 213 212 * here. 214 213 */ 215 - qcom_scm_pas_metadata_release(&pas->pas_metadata); 214 + qcom_scm_pas_metadata_release(pas->pas_ctx); 216 215 if (pas->dtb_pas_id) 217 - qcom_scm_pas_metadata_release(&pas->dtb_pas_metadata); 216 + qcom_scm_pas_metadata_release(pas->dtb_pas_ctx); 218 217 219 218 return 0; 220 219 } ··· 240 239 return ret; 241 240 } 242 241 243 - ret = qcom_mdt_pas_init(pas->dev, pas->dtb_firmware, pas->dtb_firmware_name, 244 - pas->dtb_pas_id, pas->dtb_mem_phys, 245 - &pas->dtb_pas_metadata); 246 - if (ret) 247 - goto release_dtb_firmware; 248 - 249 - ret = qcom_mdt_load_no_init(pas->dev, pas->dtb_firmware, pas->dtb_firmware_name, 250 - pas->dtb_mem_region, pas->dtb_mem_phys, 251 - pas->dtb_mem_size, &pas->dtb_mem_reloc); 242 + ret = qcom_mdt_pas_load(pas->dtb_pas_ctx, pas->dtb_firmware, 243 + pas->dtb_firmware_name, pas->dtb_mem_region, 244 + &pas->dtb_mem_reloc); 252 245 if (ret) 253 246 goto release_dtb_metadata; 254 247 } ··· 250 255 return 0; 251 256 252 257 release_dtb_metadata: 253 - qcom_scm_pas_metadata_release(&pas->dtb_pas_metadata); 254 - 255 - release_dtb_firmware: 258 + qcom_scm_pas_metadata_release(pas->dtb_pas_ctx); 256 259 release_firmware(pas->dtb_firmware); 257 260 261 + return ret; 262 + } 263 + 264 + static void qcom_pas_unmap_carveout(struct rproc *rproc, phys_addr_t mem_phys, size_t size) 265 + { 266 + if (rproc->has_iommu) 267 + iommu_unmap(rproc->domain, mem_phys, size); 268 + } 269 + 270 + static int qcom_pas_map_carveout(struct rproc *rproc, phys_addr_t mem_phys, size_t size) 271 + { 272 + int ret = 0; 273 + 274 + if (rproc->has_iommu) 275 + ret = iommu_map(rproc->domain, mem_phys, mem_phys, size, 276 + IOMMU_READ | IOMMU_WRITE, GFP_KERNEL); 258 277 return ret; 259 278 } 260 279 ··· 306 297 } 307 298 308 299 if (pas->dtb_pas_id) { 309 - ret = qcom_scm_pas_auth_and_reset(pas->dtb_pas_id); 300 + ret = qcom_pas_map_carveout(rproc, pas->dtb_mem_phys, pas->dtb_mem_size); 301 + if (ret) 302 + goto disable_px_supply; 303 + 304 + ret = qcom_scm_pas_prepare_and_auth_reset(pas->dtb_pas_ctx); 310 305 if (ret) { 311 306 dev_err(pas->dev, 312 307 "failed to authenticate dtb image and release reset\n"); 313 - goto disable_px_supply; 308 + goto unmap_dtb_carveout; 314 309 } 315 310 } 316 311 317 - ret = qcom_mdt_pas_init(pas->dev, pas->firmware, rproc->firmware, pas->pas_id, 318 - pas->mem_phys, &pas->pas_metadata); 319 - if (ret) 320 - goto disable_px_supply; 321 - 322 - ret = qcom_mdt_load_no_init(pas->dev, pas->firmware, rproc->firmware, 323 - pas->mem_region, pas->mem_phys, pas->mem_size, 324 - &pas->mem_reloc); 312 + ret = qcom_mdt_pas_load(pas->pas_ctx, pas->firmware, rproc->firmware, 313 + pas->mem_region, &pas->mem_reloc); 325 314 if (ret) 326 315 goto release_pas_metadata; 327 316 328 317 qcom_pil_info_store(pas->info_name, pas->mem_phys, pas->mem_size); 329 318 330 - ret = qcom_scm_pas_auth_and_reset(pas->pas_id); 319 + ret = qcom_pas_map_carveout(rproc, pas->mem_phys, pas->mem_size); 320 + if (ret) 321 + goto release_pas_metadata; 322 + 323 + ret = qcom_scm_pas_prepare_and_auth_reset(pas->pas_ctx); 331 324 if (ret) { 332 325 dev_err(pas->dev, 333 326 "failed to authenticate image and release reset\n"); 334 - goto release_pas_metadata; 327 + goto unmap_carveout; 335 328 } 336 329 337 330 ret = qcom_q6v5_wait_for_start(&pas->q6v5, msecs_to_jiffies(5000)); 338 331 if (ret == -ETIMEDOUT) { 339 332 dev_err(pas->dev, "start timed out\n"); 340 333 qcom_scm_pas_shutdown(pas->pas_id); 341 - goto release_pas_metadata; 334 + goto unmap_carveout; 342 335 } 343 336 344 - qcom_scm_pas_metadata_release(&pas->pas_metadata); 337 + qcom_scm_pas_metadata_release(pas->pas_ctx); 345 338 if (pas->dtb_pas_id) 346 - qcom_scm_pas_metadata_release(&pas->dtb_pas_metadata); 339 + qcom_scm_pas_metadata_release(pas->dtb_pas_ctx); 347 340 348 341 /* firmware is used to pass reference from qcom_pas_start(), drop it now */ 349 342 pas->firmware = NULL; 350 343 351 344 return 0; 352 345 346 + unmap_carveout: 347 + qcom_pas_unmap_carveout(rproc, pas->mem_phys, pas->mem_size); 353 348 release_pas_metadata: 354 - qcom_scm_pas_metadata_release(&pas->pas_metadata); 349 + qcom_scm_pas_metadata_release(pas->pas_ctx); 355 350 if (pas->dtb_pas_id) 356 - qcom_scm_pas_metadata_release(&pas->dtb_pas_metadata); 351 + qcom_scm_pas_metadata_release(pas->dtb_pas_ctx); 352 + 353 + unmap_dtb_carveout: 354 + if (pas->dtb_pas_id) 355 + qcom_pas_unmap_carveout(rproc, pas->dtb_mem_phys, pas->dtb_mem_size); 357 356 disable_px_supply: 358 357 if (pas->px_supply) 359 358 regulator_disable(pas->px_supply); ··· 417 400 ret = qcom_scm_pas_shutdown(pas->dtb_pas_id); 418 401 if (ret) 419 402 dev_err(pas->dev, "failed to shutdown dtb: %d\n", ret); 403 + 404 + qcom_pas_unmap_carveout(rproc, pas->dtb_mem_phys, pas->dtb_mem_size); 420 405 } 406 + 407 + qcom_pas_unmap_carveout(rproc, pas->mem_phys, pas->mem_size); 421 408 422 409 handover = qcom_q6v5_unprepare(&pas->q6v5); 423 410 if (handover) ··· 448 427 return pas->mem_region + offset; 449 428 } 450 429 430 + static int qcom_pas_parse_firmware(struct rproc *rproc, const struct firmware *fw) 431 + { 432 + struct qcom_pas *pas = rproc->priv; 433 + struct resource_table *table = NULL; 434 + size_t output_rt_size; 435 + void *output_rt; 436 + size_t table_sz; 437 + int ret; 438 + 439 + ret = qcom_register_dump_segments(rproc, fw); 440 + if (ret) { 441 + dev_err(pas->dev, "Error in registering dump segments\n"); 442 + return ret; 443 + } 444 + 445 + if (!rproc->has_iommu) 446 + return 0; 447 + 448 + ret = rproc_elf_load_rsc_table(rproc, fw); 449 + if (ret) 450 + dev_dbg(&rproc->dev, "Failed to load resource table from firmware\n"); 451 + 452 + table = rproc->table_ptr; 453 + table_sz = rproc->table_sz; 454 + 455 + /* 456 + * The resources consumed by Qualcomm remote processors fall into two categories: 457 + * static (such as the memory carveouts for the rproc firmware) and dynamic (like 458 + * shared memory pools). Both are managed by a Qualcomm hypervisor (such as QHEE 459 + * or Gunyah), if one is present. Otherwise, a resource table must be retrieved 460 + * via an SCM call. That table will list all dynamic resources (if any) and possibly 461 + * the static ones. The static resources may also come from a resource table embedded 462 + * in the rproc firmware instead. 463 + * 464 + * Here, we call rproc_elf_load_rsc_table() to check firmware binary has resources 465 + * or not and if it is not having then we pass NULL and zero as input resource 466 + * table pointer and size respectively to the argument of qcom_scm_pas_get_rsc_table() 467 + * and this is even true for Qualcomm remote processor who does follow remoteproc 468 + * framework. 469 + */ 470 + output_rt = qcom_scm_pas_get_rsc_table(pas->pas_ctx, table, table_sz, &output_rt_size); 471 + ret = IS_ERR(output_rt) ? PTR_ERR(output_rt) : 0; 472 + if (ret) { 473 + dev_err(pas->dev, "Error in getting resource table: %d\n", ret); 474 + return ret; 475 + } 476 + 477 + kfree(rproc->cached_table); 478 + rproc->cached_table = output_rt; 479 + rproc->table_ptr = rproc->cached_table; 480 + rproc->table_sz = output_rt_size; 481 + 482 + return ret; 483 + } 484 + 451 485 static unsigned long qcom_pas_panic(struct rproc *rproc) 452 486 { 453 487 struct qcom_pas *pas = rproc->priv; ··· 515 439 .start = qcom_pas_start, 516 440 .stop = qcom_pas_stop, 517 441 .da_to_va = qcom_pas_da_to_va, 518 - .parse_fw = qcom_register_dump_segments, 442 + .parse_fw = qcom_pas_parse_firmware, 519 443 .load = qcom_pas_load, 520 444 .panic = qcom_pas_panic, 521 445 }; ··· 525 449 .start = qcom_pas_start, 526 450 .stop = qcom_pas_stop, 527 451 .da_to_va = qcom_pas_da_to_va, 528 - .parse_fw = qcom_register_dump_segments, 452 + .parse_fw = qcom_pas_parse_firmware, 529 453 .load = qcom_pas_load, 530 454 .panic = qcom_pas_panic, 531 455 .coredump = qcom_pas_minidump, ··· 773 697 return -ENOMEM; 774 698 } 775 699 700 + rproc->has_iommu = of_property_present(pdev->dev.of_node, "iommus"); 776 701 rproc->auto_boot = desc->auto_boot; 777 702 rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE); 778 703 ··· 837 760 } 838 761 839 762 qcom_add_ssr_subdev(rproc, &pas->ssr_subdev, desc->ssr_name); 763 + 764 + pas->pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->pas_id, 765 + pas->mem_phys, pas->mem_size); 766 + if (IS_ERR(pas->pas_ctx)) { 767 + ret = PTR_ERR(pas->pas_ctx); 768 + goto remove_ssr_sysmon; 769 + } 770 + 771 + pas->dtb_pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->dtb_pas_id, 772 + pas->dtb_mem_phys, 773 + pas->dtb_mem_size); 774 + if (IS_ERR(pas->dtb_pas_ctx)) { 775 + ret = PTR_ERR(pas->dtb_pas_ctx); 776 + goto remove_ssr_sysmon; 777 + } 778 + 779 + pas->pas_ctx->use_tzmem = rproc->has_iommu; 780 + pas->dtb_pas_ctx->use_tzmem = rproc->has_iommu; 840 781 ret = rproc_add(rproc); 841 782 if (ret) 842 783 goto remove_ssr_sysmon;
+4 -3
drivers/soc/qcom/cmd-db.c
··· 349 349 return -EINVAL; 350 350 } 351 351 352 - cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WC); 353 - if (!cmd_db_header) { 354 - ret = -ENOMEM; 352 + cmd_db_header = devm_memremap(&pdev->dev, rmem->base, rmem->size, MEMREMAP_WC); 353 + if (IS_ERR(cmd_db_header)) { 354 + ret = PTR_ERR(cmd_db_header); 355 355 cmd_db_header = NULL; 356 356 return ret; 357 357 } 358 358 359 359 if (!cmd_db_magic_matches(cmd_db_header)) { 360 360 dev_err(&pdev->dev, "Invalid Command DB Magic\n"); 361 + cmd_db_header = NULL; 361 362 return -EINVAL; 362 363 } 363 364
+207
drivers/soc/qcom/llcc-qcom.c
··· 182 182 LLCC_TRP_WRS_CACHEABLE_EN, 183 183 }; 184 184 185 + static const struct llcc_slice_config glymur_data[] = { 186 + { 187 + .usecase_id = LLCC_CPUSS, 188 + .slice_id = 1, 189 + .max_cap = 7680, 190 + .priority = 1, 191 + .bonus_ways = 0xFFF, 192 + .res_ways = 0x0, 193 + .vict_prio = true, 194 + .activate_on_init = true, 195 + }, { 196 + .usecase_id = LLCC_VIDSC0, 197 + .slice_id = 2, 198 + .max_cap = 512, 199 + .priority = 3, 200 + .fixed_size = true, 201 + .bonus_ways = 0xFFF, 202 + .res_ways = 0x0, 203 + .vict_prio = true, 204 + }, { 205 + .usecase_id = LLCC_AUDIO, 206 + .slice_id = 6, 207 + .max_cap = 1024, 208 + .priority = 1, 209 + .fixed_size = true, 210 + .bonus_ways = 0xFFF, 211 + .res_ways = 0x0, 212 + .vict_prio = true, 213 + }, { 214 + .usecase_id = LLCC_VIDSC1, 215 + .slice_id = 4, 216 + .max_cap = 512, 217 + .priority = 3, 218 + .fixed_size = true, 219 + .bonus_ways = 0xFFF, 220 + .res_ways = 0x0, 221 + .vict_prio = true, 222 + }, { 223 + .usecase_id = LLCC_CMPT, 224 + .slice_id = 10, 225 + .max_cap = 7680, 226 + .priority = 1, 227 + .fixed_size = true, 228 + .bonus_ways = 0xFFF, 229 + .res_ways = 0x0, 230 + .vict_prio = true, 231 + }, { 232 + .usecase_id = LLCC_GPUHTW, 233 + .slice_id = 11, 234 + .max_cap = 512, 235 + .priority = 1, 236 + .fixed_size = true, 237 + .bonus_ways = 0xFFF, 238 + .res_ways = 0x0, 239 + .vict_prio = true, 240 + }, { 241 + .usecase_id = LLCC_GPU, 242 + .slice_id = 9, 243 + .max_cap = 7680, 244 + .priority = 1, 245 + .bonus_ways = 0xFFF, 246 + .res_ways = 0x0, 247 + .write_scid_en = true, 248 + .write_scid_cacheable_en = true, 249 + .stale_en = true, 250 + .vict_prio = true, 251 + }, { 252 + .usecase_id = LLCC_MMUHWT, 253 + .slice_id = 18, 254 + .max_cap = 768, 255 + .priority = 1, 256 + .fixed_size = true, 257 + .bonus_ways = 0xFFF, 258 + .res_ways = 0x0, 259 + .vict_prio = true, 260 + .activate_on_init = true, 261 + }, { 262 + .usecase_id = LLCC_AUDHW, 263 + .slice_id = 22, 264 + .max_cap = 1024, 265 + .priority = 1, 266 + .fixed_size = true, 267 + .bonus_ways = 0xFFF, 268 + .res_ways = 0x0, 269 + .vict_prio = true, 270 + }, { 271 + .usecase_id = LLCC_CVP, 272 + .slice_id = 8, 273 + .max_cap = 64, 274 + .priority = 3, 275 + .fixed_size = true, 276 + .bonus_ways = 0xFFF, 277 + .res_ways = 0x0, 278 + .vict_prio = true, 279 + }, { 280 + .usecase_id = LLCC_WRCACHE, 281 + .slice_id = 31, 282 + .max_cap = 1536, 283 + .priority = 1, 284 + .fixed_size = true, 285 + .bonus_ways = 0xFFF, 286 + .res_ways = 0x0, 287 + .vict_prio = true, 288 + .activate_on_init = true, 289 + }, { 290 + .usecase_id = LLCC_CMPTHCP, 291 + .slice_id = 17, 292 + .max_cap = 256, 293 + .priority = 3, 294 + .fixed_size = true, 295 + .bonus_ways = 0xFFF, 296 + .res_ways = 0x0, 297 + .vict_prio = true, 298 + }, { 299 + .usecase_id = LLCC_LCPDARE, 300 + .slice_id = 30, 301 + .max_cap = 768, 302 + .priority = 3, 303 + .fixed_size = true, 304 + .bonus_ways = 0xFFF, 305 + .res_ways = 0x0, 306 + .alloc_oneway_en = true, 307 + .vict_prio = true, 308 + .activate_on_init = true, 309 + }, { 310 + .usecase_id = LLCC_AENPU, 311 + .slice_id = 3, 312 + .max_cap = 3072, 313 + .priority = 1, 314 + .fixed_size = true, 315 + .bonus_ways = 0xFFF, 316 + .res_ways = 0x0, 317 + .cache_mode = 2, 318 + .vict_prio = true, 319 + }, { 320 + .usecase_id = LLCC_ISLAND1, 321 + .slice_id = 12, 322 + .max_cap = 5632, 323 + .priority = 7, 324 + .fixed_size = true, 325 + .bonus_ways = 0x0, 326 + .res_ways = 0x7FF, 327 + .vict_prio = true, 328 + }, { 329 + .usecase_id = LLCC_VIDVSP, 330 + .slice_id = 28, 331 + .max_cap = 256, 332 + .priority = 3, 333 + .fixed_size = true, 334 + .bonus_ways = 0xFFF, 335 + .res_ways = 0x0, 336 + .vict_prio = true, 337 + }, { 338 + .usecase_id = LLCC_OOBM_NS, 339 + .slice_id = 5, 340 + .max_cap = 512, 341 + .priority = 1, 342 + .bonus_ways = 0xFFF, 343 + .res_ways = 0x0, 344 + .vict_prio = true, 345 + }, { 346 + .usecase_id = LLCC_CPUSS_OPP, 347 + .slice_id = 32, 348 + .max_cap = 0, 349 + .fixed_size = true, 350 + .bonus_ways = 0x0, 351 + .res_ways = 0x0, 352 + .vict_prio = true, 353 + .activate_on_init = true, 354 + }, { 355 + .usecase_id = LLCC_PCIE_TCU, 356 + .slice_id = 19, 357 + .max_cap = 256, 358 + .priority = 1, 359 + .fixed_size = true, 360 + .bonus_ways = 0xFFF, 361 + .res_ways = 0x0, 362 + .vict_prio = true, 363 + .activate_on_init = true, 364 + }, { 365 + .usecase_id = LLCC_VIDSC_VSP1, 366 + .slice_id = 29, 367 + .max_cap = 256, 368 + .priority = 3, 369 + .fixed_size = true, 370 + .bonus_ways = 0xFFF, 371 + .res_ways = 0x0, 372 + .vict_prio = true, 373 + } 374 + }; 375 + 185 376 static const struct llcc_slice_config ipq5424_data[] = { 186 377 { 187 378 .usecase_id = LLCC_CPUSS, ··· 4063 3872 }, 4064 3873 }; 4065 3874 3875 + static const struct qcom_llcc_config glymur_cfg[] = { 3876 + { 3877 + .sct_data = glymur_data, 3878 + .size = ARRAY_SIZE(glymur_data), 3879 + .reg_offset = llcc_v6_reg_offset, 3880 + .edac_reg_offset = &llcc_v2_1_edac_reg_offset, 3881 + .no_edac = true, 3882 + }, 3883 + }; 3884 + 4066 3885 static const struct qcom_llcc_config qcs615_cfg[] = { 4067 3886 { 4068 3887 .sct_data = qcs615_data, ··· 4302 4101 static const struct qcom_sct_config kaanapali_cfgs = { 4303 4102 .llcc_config = kaanapali_cfg, 4304 4103 .num_config = ARRAY_SIZE(kaanapali_cfg), 4104 + }; 4105 + 4106 + static const struct qcom_sct_config glymur_cfgs = { 4107 + .llcc_config = glymur_cfg, 4108 + .num_config = ARRAY_SIZE(glymur_cfg), 4305 4109 }; 4306 4110 4307 4111 static const struct qcom_sct_config qcs615_cfgs = { ··· 5147 4941 } 5148 4942 5149 4943 static const struct of_device_id qcom_llcc_of_match[] = { 4944 + { .compatible = "qcom,glymur-llcc", .data = &glymur_cfgs }, 5150 4945 { .compatible = "qcom,ipq5424-llcc", .data = &ipq5424_cfgs}, 5151 4946 { .compatible = "qcom,kaanapali-llcc", .data = &kaanapali_cfgs}, 5152 4947 { .compatible = "qcom,qcs615-llcc", .data = &qcs615_cfgs},
+35 -16
drivers/soc/qcom/mdt_loader.c
··· 227 227 } 228 228 EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata); 229 229 230 - /** 231 - * qcom_mdt_pas_init() - initialize PAS region for firmware loading 232 - * @dev: device handle to associate resources with 233 - * @fw: firmware object for the mdt file 234 - * @fw_name: name of the firmware, for construction of segment file names 235 - * @pas_id: PAS identifier 236 - * @mem_phys: physical address of allocated memory region 237 - * @ctx: PAS metadata context, to be released by caller 238 - * 239 - * Returns 0 on success, negative errno otherwise. 240 - */ 241 - int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, 242 - const char *fw_name, int pas_id, phys_addr_t mem_phys, 243 - struct qcom_scm_pas_metadata *ctx) 230 + static int __qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, 231 + const char *fw_name, int pas_id, phys_addr_t mem_phys, 232 + struct qcom_scm_pas_context *ctx) 244 233 { 245 234 const struct elf32_phdr *phdrs; 246 235 const struct elf32_phdr *phdr; ··· 291 302 out: 292 303 return ret; 293 304 } 294 - EXPORT_SYMBOL_GPL(qcom_mdt_pas_init); 295 305 296 306 static bool qcom_mdt_bins_are_split(const struct firmware *fw) 297 307 { ··· 457 469 { 458 470 int ret; 459 471 460 - ret = qcom_mdt_pas_init(dev, fw, fw_name, pas_id, mem_phys, NULL); 472 + ret = __qcom_mdt_pas_init(dev, fw, fw_name, pas_id, mem_phys, NULL); 461 473 if (ret) 462 474 return ret; 463 475 ··· 465 477 mem_size, reloc_base); 466 478 } 467 479 EXPORT_SYMBOL_GPL(qcom_mdt_load); 480 + 481 + /** 482 + * qcom_mdt_pas_load - Loads and authenticates the metadata of the firmware 483 + * (typically contained in the .mdt file), followed by loading the actual 484 + * firmware segments (e.g., .bXX files). Authentication of the segments done 485 + * by a separate call. 486 + * 487 + * The PAS context must be initialized using qcom_scm_pas_context_init() 488 + * prior to invoking this function. 489 + * 490 + * @ctx: Pointer to the PAS (Peripheral Authentication Service) context 491 + * @fw: Firmware object representing the .mdt file 492 + * @firmware: Name of the firmware used to construct segment file names 493 + * @mem_region: Memory region allocated for loading the firmware 494 + * @reloc_base: Physical address adjusted after relocation 495 + * 496 + * Return: 0 on success or a negative error code on failure. 497 + */ 498 + int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw, 499 + const char *firmware, void *mem_region, phys_addr_t *reloc_base) 500 + { 501 + int ret; 502 + 503 + ret = __qcom_mdt_pas_init(ctx->dev, fw, firmware, ctx->pas_id, ctx->mem_phys, ctx); 504 + if (ret) 505 + return ret; 506 + 507 + return qcom_mdt_load_no_init(ctx->dev, fw, firmware, mem_region, ctx->mem_phys, 508 + ctx->mem_size, reloc_base); 509 + } 510 + EXPORT_SYMBOL_GPL(qcom_mdt_pas_load); 468 511 469 512 MODULE_DESCRIPTION("Firmware parser for Qualcomm MDT format"); 470 513 MODULE_LICENSE("GPL v2");
+118 -19
drivers/soc/qcom/qmi_encdec.c
··· 23 23 *p_length |= ((u8)*p_src) << 8; \ 24 24 } while (0) 25 25 26 - #define QMI_ENCDEC_ENCODE_N_BYTES(p_dst, p_src, size) \ 26 + #define QMI_ENCDEC_ENCODE_U8(p_dst, p_src) \ 27 27 do { \ 28 - memcpy(p_dst, p_src, size); \ 29 - p_dst = (u8 *)p_dst + size; \ 30 - p_src = (u8 *)p_src + size; \ 28 + memcpy(p_dst, p_src, sizeof(u8)); \ 29 + p_dst = (u8 *)p_dst + sizeof(u8); \ 30 + p_src = (u8 *)p_src + sizeof(u8); \ 31 31 } while (0) 32 32 33 - #define QMI_ENCDEC_DECODE_N_BYTES(p_dst, p_src, size) \ 33 + #define QMI_ENCDEC_ENCODE_U16(p_dst, p_src) \ 34 34 do { \ 35 - memcpy(p_dst, p_src, size); \ 36 - p_dst = (u8 *)p_dst + size; \ 37 - p_src = (u8 *)p_src + size; \ 35 + *(__le16 *)p_dst = __cpu_to_le16(*(u16 *)p_src); \ 36 + p_dst = (u8 *)p_dst + sizeof(u16); \ 37 + p_src = (u8 *)p_src + sizeof(u16); \ 38 + } while (0) 39 + 40 + #define QMI_ENCDEC_ENCODE_U32(p_dst, p_src) \ 41 + do { \ 42 + *(__le32 *)p_dst = __cpu_to_le32(*(u32 *)p_src); \ 43 + p_dst = (u8 *)p_dst + sizeof(u32); \ 44 + p_src = (u8 *)p_src + sizeof(u32); \ 45 + } while (0) 46 + 47 + #define QMI_ENCDEC_ENCODE_U64(p_dst, p_src) \ 48 + do { \ 49 + *(__le64 *)p_dst = __cpu_to_le64(*(u64 *)p_src); \ 50 + p_dst = (u8 *)p_dst + sizeof(u64); \ 51 + p_src = (u8 *)p_src + sizeof(u64); \ 52 + } while (0) 53 + 54 + #define QMI_ENCDEC_DECODE_U8(p_dst, p_src) \ 55 + do { \ 56 + memcpy(p_dst, p_src, sizeof(u8)); \ 57 + p_dst = (u8 *)p_dst + sizeof(u8); \ 58 + p_src = (u8 *)p_src + sizeof(u8); \ 59 + } while (0) 60 + 61 + #define QMI_ENCDEC_DECODE_U16(p_dst, p_src) \ 62 + do { \ 63 + *(u16 *)p_dst = __le16_to_cpu(*(__le16 *)p_src); \ 64 + p_dst = (u8 *)p_dst + sizeof(u16); \ 65 + p_src = (u8 *)p_src + sizeof(u16); \ 66 + } while (0) 67 + 68 + #define QMI_ENCDEC_DECODE_U32(p_dst, p_src) \ 69 + do { \ 70 + *(u32 *)p_dst = __le32_to_cpu(*(__le32 *)p_src); \ 71 + p_dst = (u8 *)p_dst + sizeof(u32); \ 72 + p_src = (u8 *)p_src + sizeof(u32); \ 73 + } while (0) 74 + 75 + #define QMI_ENCDEC_DECODE_U64(p_dst, p_src) \ 76 + do { \ 77 + *(u64 *)p_dst = __le64_to_cpu(*(__le64 *)p_src); \ 78 + p_dst = (u8 *)p_dst + sizeof(u64); \ 79 + p_src = (u8 *)p_src + sizeof(u64); \ 38 80 } while (0) 39 81 40 82 #define UPDATE_ENCODE_VARIABLES(temp_si, buf_dst, \ ··· 203 161 * of primary data type which include u8 - u64 or similar. This 204 162 * function returns the number of bytes of encoded information. 205 163 * 206 - * Return: The number of bytes of encoded information. 164 + * Return: The number of bytes of encoded information on success or negative 165 + * errno on error. 207 166 */ 208 167 static int qmi_encode_basic_elem(void *buf_dst, const void *buf_src, 209 168 u32 elem_len, u32 elem_size) ··· 212 169 u32 i, rc = 0; 213 170 214 171 for (i = 0; i < elem_len; i++) { 215 - QMI_ENCDEC_ENCODE_N_BYTES(buf_dst, buf_src, elem_size); 172 + switch (elem_size) { 173 + case sizeof(u8): 174 + QMI_ENCDEC_ENCODE_U8(buf_dst, buf_src); 175 + break; 176 + case sizeof(u16): 177 + QMI_ENCDEC_ENCODE_U16(buf_dst, buf_src); 178 + break; 179 + case sizeof(u32): 180 + QMI_ENCDEC_ENCODE_U32(buf_dst, buf_src); 181 + break; 182 + case sizeof(u64): 183 + QMI_ENCDEC_ENCODE_U64(buf_dst, buf_src); 184 + break; 185 + default: 186 + pr_err("%s: Unrecognized element size\n", __func__); 187 + return -EINVAL; 188 + } 189 + 216 190 rc += elem_size; 217 191 } 218 192 ··· 327 267 } 328 268 rc = qmi_encode_basic_elem(buf_dst, &string_len, 329 269 1, string_len_sz); 270 + if (rc < 0) 271 + return rc; 330 272 encoded_bytes += rc; 331 273 } 332 274 333 275 rc = qmi_encode_basic_elem(buf_dst + encoded_bytes, buf_src, 334 276 string_len, temp_ei->elem_size); 277 + if (rc < 0) 278 + return rc; 335 279 encoded_bytes += rc; 336 280 337 281 return encoded_bytes; ··· 397 333 case QMI_OPT_FLAG: 398 334 rc = qmi_encode_basic_elem(&opt_flag_value, buf_src, 399 335 1, sizeof(u8)); 336 + if (rc < 0) 337 + return rc; 400 338 if (opt_flag_value) 401 339 temp_ei = temp_ei + 1; 402 340 else ··· 406 340 break; 407 341 408 342 case QMI_DATA_LEN: 343 + memcpy(&data_len_value, buf_src, sizeof(u32)); 409 344 data_len_sz = temp_ei->elem_size == sizeof(u8) ? 410 345 sizeof(u8) : sizeof(u16); 411 346 /* Check to avoid out of range buffer access */ ··· 417 350 return -ETOOSMALL; 418 351 } 419 352 if (data_len_sz == sizeof(u8)) { 420 - val8 = *(u8 *)buf_src; 421 - data_len_value = (u32)val8; 353 + val8 = data_len_value; 422 354 rc = qmi_encode_basic_elem(buf_dst, &val8, 423 355 1, data_len_sz); 356 + if (rc < 0) 357 + return rc; 424 358 } else { 425 - val16 = *(u16 *)buf_src; 426 - data_len_value = (u32)le16_to_cpu(val16); 359 + val16 = data_len_value; 427 360 rc = qmi_encode_basic_elem(buf_dst, &val16, 428 361 1, data_len_sz); 362 + if (rc < 0) 363 + return rc; 429 364 } 430 365 UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst, 431 366 encoded_bytes, tlv_len, ··· 455 386 rc = qmi_encode_basic_elem(buf_dst, buf_src, 456 387 data_len_value, 457 388 temp_ei->elem_size); 389 + if (rc < 0) 390 + return rc; 458 391 UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst, 459 392 encoded_bytes, tlv_len, 460 393 encode_tlv, rc); ··· 515 444 * of primary data type which include u8 - u64 or similar. This 516 445 * function returns the number of bytes of decoded information. 517 446 * 518 - * Return: The total size of the decoded data elements, in bytes. 447 + * Return: The total size of the decoded data elements, in bytes, on success or 448 + * negative errno on error. 519 449 */ 520 450 static int qmi_decode_basic_elem(void *buf_dst, const void *buf_src, 521 451 u32 elem_len, u32 elem_size) ··· 524 452 u32 i, rc = 0; 525 453 526 454 for (i = 0; i < elem_len; i++) { 527 - QMI_ENCDEC_DECODE_N_BYTES(buf_dst, buf_src, elem_size); 455 + switch (elem_size) { 456 + case sizeof(u8): 457 + QMI_ENCDEC_DECODE_U8(buf_dst, buf_src); 458 + break; 459 + case sizeof(u16): 460 + QMI_ENCDEC_DECODE_U16(buf_dst, buf_src); 461 + break; 462 + case sizeof(u32): 463 + QMI_ENCDEC_DECODE_U32(buf_dst, buf_src); 464 + break; 465 + case sizeof(u64): 466 + QMI_ENCDEC_DECODE_U64(buf_dst, buf_src); 467 + break; 468 + default: 469 + pr_err("%s: Unrecognized element size\n", __func__); 470 + return -EINVAL; 471 + } 472 + 528 473 rc += elem_size; 529 474 } 530 475 ··· 633 544 if (string_len_sz == sizeof(u8)) { 634 545 rc = qmi_decode_basic_elem(&val8, buf_src, 635 546 1, string_len_sz); 547 + if (rc < 0) 548 + return rc; 636 549 string_len = (u32)val8; 637 550 } else { 638 551 rc = qmi_decode_basic_elem(&val16, buf_src, 639 552 1, string_len_sz); 553 + if (rc < 0) 554 + return rc; 640 555 string_len = (u32)val16; 641 556 } 642 557 decoded_bytes += rc; ··· 658 565 659 566 rc = qmi_decode_basic_elem(buf_dst, buf_src + decoded_bytes, 660 567 string_len, temp_ei->elem_size); 568 + if (rc < 0) 569 + return rc; 661 570 *((char *)buf_dst + string_len) = '\0'; 662 571 decoded_bytes += rc; 663 572 ··· 720 625 int rc; 721 626 u8 val8; 722 627 u16 val16; 723 - u32 val32; 724 628 725 629 while (decoded_bytes < in_buf_len) { 726 630 if (dec_level >= 2 && temp_ei->data_type == QMI_EOTI) ··· 761 667 if (data_len_sz == sizeof(u8)) { 762 668 rc = qmi_decode_basic_elem(&val8, buf_src, 763 669 1, data_len_sz); 670 + if (rc < 0) 671 + return rc; 764 672 data_len_value = (u32)val8; 765 673 } else { 766 674 rc = qmi_decode_basic_elem(&val16, buf_src, 767 675 1, data_len_sz); 676 + if (rc < 0) 677 + return rc; 768 678 data_len_value = (u32)val16; 769 679 } 770 - val32 = cpu_to_le32(data_len_value); 771 - memcpy(buf_dst, &val32, sizeof(u32)); 680 + memcpy(buf_dst, &data_len_value, sizeof(u32)); 772 681 temp_ei = temp_ei + 1; 773 682 buf_dst = out_c_struct + temp_ei->offset; 774 683 tlv_len -= data_len_sz; ··· 798 701 rc = qmi_decode_basic_elem(buf_dst, buf_src, 799 702 data_len_value, 800 703 temp_ei->elem_size); 704 + if (rc < 0) 705 + return rc; 801 706 UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc); 802 707 break; 803 708
+3 -1
drivers/soc/qcom/smem.c
··· 1219 1219 smem->item_count = qcom_smem_get_item_count(smem); 1220 1220 break; 1221 1221 case SMEM_GLOBAL_HEAP_VERSION: 1222 - qcom_smem_map_global(smem, size); 1222 + ret = qcom_smem_map_global(smem, size); 1223 + if (ret < 0) 1224 + return ret; 1223 1225 smem->item_count = SMEM_ITEM_COUNT; 1224 1226 break; 1225 1227 default:
+22 -8
include/linux/firmware/qcom/qcom_scm.h
··· 66 66 void qcom_scm_cpu_power_down(u32 flags); 67 67 int qcom_scm_set_remote_state(u32 state, u32 id); 68 68 69 - struct qcom_scm_pas_metadata { 69 + struct qcom_scm_pas_context { 70 + struct device *dev; 71 + u32 pas_id; 72 + phys_addr_t mem_phys; 73 + size_t mem_size; 70 74 void *ptr; 71 75 dma_addr_t phys; 72 76 ssize_t size; 77 + bool use_tzmem; 73 78 }; 74 79 75 - int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size, 76 - struct qcom_scm_pas_metadata *ctx); 77 - void qcom_scm_pas_metadata_release(struct qcom_scm_pas_metadata *ctx); 78 - int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size); 79 - int qcom_scm_pas_auth_and_reset(u32 peripheral); 80 - int qcom_scm_pas_shutdown(u32 peripheral); 81 - bool qcom_scm_pas_supported(u32 peripheral); 80 + struct qcom_scm_pas_context *devm_qcom_scm_pas_context_alloc(struct device *dev, 81 + u32 pas_id, 82 + phys_addr_t mem_phys, 83 + size_t mem_size); 84 + int qcom_scm_pas_init_image(u32 pas_id, const void *metadata, size_t size, 85 + struct qcom_scm_pas_context *ctx); 86 + void qcom_scm_pas_metadata_release(struct qcom_scm_pas_context *ctx); 87 + int qcom_scm_pas_mem_setup(u32 pas_id, phys_addr_t addr, phys_addr_t size); 88 + int qcom_scm_pas_auth_and_reset(u32 pas_id); 89 + int qcom_scm_pas_shutdown(u32 pas_id); 90 + bool qcom_scm_pas_supported(u32 pas_id); 91 + struct resource_table *qcom_scm_pas_get_rsc_table(struct qcom_scm_pas_context *ctx, 92 + void *input_rt, size_t input_rt_size, 93 + size_t *output_rt_size); 94 + 95 + int qcom_scm_pas_prepare_and_auth_reset(struct qcom_scm_pas_context *ctx); 82 96 83 97 int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val); 84 98 int qcom_scm_io_writel(phys_addr_t addr, unsigned int val);
+4
include/linux/soc/qcom/llcc-qcom.h
··· 74 74 #define LLCC_CAMSRTIP 73 75 75 #define LLCC_CAMRTRF 74 76 76 #define LLCC_CAMSRTRF 75 77 + #define LLCC_OOBM_NS 81 78 + #define LLCC_OOBM_S 82 77 79 #define LLCC_VIDEO_APV 83 78 80 #define LLCC_COMPUTE1 87 79 81 #define LLCC_CPUSS_OPP 88 80 82 #define LLCC_CPUSSMPAM 89 83 + #define LLCC_VIDSC_VSP1 91 81 84 #define LLCC_CAM_IPE_STROV 92 82 85 #define LLCC_CAM_OFE_STROV 93 83 86 #define LLCC_CPUSS_HEU 94 87 + #define LLCC_PCIE_TCU 97 84 88 #define LLCC_MDM_PNG_FIXED 100 85 89 86 90 /**
+11 -11
include/linux/soc/qcom/mdt_loader.h
··· 10 10 11 11 struct device; 12 12 struct firmware; 13 - struct qcom_scm_pas_metadata; 13 + struct qcom_scm_pas_context; 14 14 15 15 #if IS_ENABLED(CONFIG_QCOM_MDT_LOADER) 16 16 17 17 ssize_t qcom_mdt_get_size(const struct firmware *fw); 18 - int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, 19 - const char *fw_name, int pas_id, phys_addr_t mem_phys, 20 - struct qcom_scm_pas_metadata *pas_metadata_ctx); 21 18 int qcom_mdt_load(struct device *dev, const struct firmware *fw, 22 19 const char *fw_name, int pas_id, void *mem_region, 23 20 phys_addr_t mem_phys, size_t mem_size, 24 21 phys_addr_t *reloc_base); 22 + 23 + int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw, 24 + const char *firmware, void *mem_region, phys_addr_t *reloc_base); 25 25 26 26 int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw, 27 27 const char *fw_name, void *mem_region, ··· 37 37 return -ENODEV; 38 38 } 39 39 40 - static inline int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, 41 - const char *fw_name, int pas_id, phys_addr_t mem_phys, 42 - struct qcom_scm_pas_metadata *pas_metadata_ctx) 43 - { 44 - return -ENODEV; 45 - } 46 - 47 40 static inline int qcom_mdt_load(struct device *dev, const struct firmware *fw, 48 41 const char *fw_name, int pas_id, 49 42 void *mem_region, phys_addr_t mem_phys, 50 43 size_t mem_size, phys_addr_t *reloc_base) 44 + { 45 + return -ENODEV; 46 + } 47 + 48 + static inline int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, 49 + const struct firmware *fw, const char *firmware, 50 + void *mem_region, phys_addr_t *reloc_base) 51 51 { 52 52 return -ENODEV; 53 53 }
+1
include/linux/soc/qcom/ubwc.h
··· 8 8 #define __QCOM_UBWC_H__ 9 9 10 10 #include <linux/bits.h> 11 + #include <linux/printk.h> 11 12 #include <linux/types.h> 12 13 13 14 struct qcom_ubwc_cfg_data {