From 32076a9a1fecef44dc1d6cdb72148ad64e6a24b6 Mon Sep 17 00:00:00 2001 From: classabbyamp Date: Thu, 21 Mar 2024 18:00:45 -0400 Subject: [PATCH 1/2] New package: x13s-base-0.4 --- srcpkgs/x13s-base/INSTALL | 16 ++++++++++++++++ srcpkgs/x13s-base/files/72-touchscreen.rules | 1 + srcpkgs/x13s-base/files/90-bt-address.sh | 4 ++++ srcpkgs/x13s-base/files/90-net-address.rules | 2 ++ srcpkgs/x13s-base/files/dracut.conf | 6 ++++++ srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++ srcpkgs/x13s-base/template | 19 +++++++++++++++++++ 7 files changed, 54 insertions(+) create mode 100644 srcpkgs/x13s-base/INSTALL create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules create mode 100644 srcpkgs/x13s-base/files/90-bt-address.sh create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules create mode 100644 srcpkgs/x13s-base/files/dracut.conf create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf create mode 100644 srcpkgs/x13s-base/template diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL new file mode 100644 index 00000000000000..c30648a8f3d2e0 --- /dev/null +++ b/srcpkgs/x13s-base/INSTALL @@ -0,0 +1,16 @@ +case "$ACTION" in +post) + mkdir -p etc/runit/runsvdir/default/ + ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/ + + # assign a random wlan MAC address with the correct OUI + sed -i.bak -e "s/:AA:BB:CC/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \ + usr/lib/udev/rules.d/90-x13s-net-address.rules + rm -f usr/lib/udev/rules.d/90-x13s-net-address.rules.bak + + # assign a random bluetooth MAC address with the correct OUI + sed -i.bak -e "s/:AA:BB:CC/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \ + etc/runit/core-services/90-x13s-bt-address.sh + rm -f usr/lib/udev/rules.d/90-x13s-bt-address.sh.bak + ;; +esac diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules new file mode 100644 index 00000000000000..c0a1cb63749643 --- /dev/null +++ b/srcpkgs/x13s-base/files/72-touchscreen.rules @@ -0,0 +1 @@ +ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'" diff --git a/srcpkgs/x13s-base/files/90-bt-address.sh b/srcpkgs/x13s-base/files/90-bt-address.sh new file mode 100644 index 00000000000000..9c0be47992efb5 --- /dev/null +++ b/srcpkgs/x13s-base/files/90-bt-address.sh @@ -0,0 +1,4 @@ +if type btmgmt >/dev/null 2>&1; then + msg "Setting bluetooth MAC address..." + btmgmt --index 0 public-addr F4:A0:0D:AA:BB:CC +fi diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules new file mode 100644 index 00000000000000..c16e39b9df089e --- /dev/null +++ b/srcpkgs/x13s-base/files/90-net-address.rules @@ -0,0 +1,2 @@ +ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", \ + RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:AA:BB:CC" diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf new file mode 100644 index 00000000000000..a24acfa3d0a06e --- /dev/null +++ b/srcpkgs/x13s-base/files/dracut.conf @@ -0,0 +1,6 @@ +force_drivers+=" nvme phy_qcom_qmp_pcie " +# keyboard +force_drivers+=" i2c_hid_of i2c_qcom_geni " +# display +force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm " +force_drivers+=" phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp " diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf new file mode 100644 index 00000000000000..a428eefb2016f9 --- /dev/null +++ b/srcpkgs/x13s-base/files/mkinitcpio.conf @@ -0,0 +1,6 @@ +MODULES+=(nvme phy_qcom_qmp_pcie) +# keyboard +MODULES+=(i2c_hid_of i2c_qcom_geni) +# display +MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm + phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp) diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template new file mode 100644 index 00000000000000..5956eaa6bac558 --- /dev/null +++ b/srcpkgs/x13s-base/template @@ -0,0 +1,19 @@ +# Template file for 'x13s-base' +pkgname=x13s-base +version=0.4 +revision=1 +archs="aarch64*" +depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network + alsa-ucm-conf qrtr-ns" +short_desc="Void Linux Thinkpad X13s platform package" +maintainer="classabbyamp " +license="Public Domain" +homepage="https://www.voidlinux.org" + +do_install() { + vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 72-x13s-touchscreen.rules + vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules + vinstall "${FILESDIR}"/90-bt-address.sh 644 etc/runit/core-services 90-x13s-bt-address.sh + vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf + vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf +} From 3829d3f52e4968f42b247acebb1501e0c3ef58cd Mon Sep 17 00:00:00 2001 From: classabbyamp Date: Thu, 21 Mar 2024 18:01:30 -0400 Subject: [PATCH 2/2] linux6.8: add support for lenovo x13s --- srcpkgs/linux6.8/files/arm64-dotconfig | 81 +- ...d-in-kernel-pd-mapper-implementation.patch | 1964 +++++++++++++++++ srcpkgs/linux6.8/template | 2 +- 3 files changed, 2023 insertions(+), 24 deletions(-) create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig index c83b61e5fcbe2f..ee27ce08cf34f3 100644 --- a/srcpkgs/linux6.8/files/arm64-dotconfig +++ b/srcpkgs/linux6.8/files/arm64-dotconfig @@ -2,7 +2,7 @@ # Automatically generated file; DO NOT EDIT. # Linux/arm64 6.8.9 Kernel Configuration # -CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0" +CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=130200 CONFIG_CLANG_VERSION=0 @@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y CONFIG_INIT_ENV_ARG_LIMIT=32 # CONFIG_COMPILE_TEST is not set # CONFIG_WERROR is not set -CONFIG_LOCALVERSION="_1" +CONFIG_LOCALVERSION="_2" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_BUILD_SALT="" CONFIG_DEFAULT_INIT="" @@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y CONFIG_DPM_WATCHDOG_TIMEOUT=60 CONFIG_PM_CLK=y CONFIG_PM_GENERIC_DOMAINS=y -# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y CONFIG_PM_GENERIC_DOMAINS_SLEEP=y CONFIG_PM_GENERIC_DOMAINS_OF=y CONFIG_CPU_PM=y @@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y CONFIG_REGMAP=y CONFIG_REGMAP_I2C=y CONFIG_REGMAP_SPI=y -CONFIG_REGMAP_SPMI=m +CONFIG_REGMAP_SPMI=y CONFIG_REGMAP_W1=m CONFIG_REGMAP_MMIO=y CONFIG_REGMAP_IRQ=y @@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y CONFIG_ARM_SCMI_POWER_CONTROL=m # end of ARM System Control and Management Interface Protocol -CONFIG_ARM_SCPI_PROTOCOL=m +CONFIG_ARM_SCPI_PROTOCOL=y CONFIG_ARM_SDE_INTERFACE=y CONFIG_FIRMWARE_MEMMAP=y CONFIG_DMIID=y @@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y # CONFIG_QCOM_SCM=y # CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set -# CONFIG_QCOM_QSEECOM is not set +CONFIG_QCOM_QSEECOM=y +CONFIG_QCOM_QSEECOM_UEFISECAPP=y # end of Qualcomm firmware drivers CONFIG_HAVE_ARM_SMCCC=y @@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m CONFIG_I2C=y CONFIG_ACPI_I2C_OPREGION=y CONFIG_I2C_BOARDINFO=y -# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_COMPAT=y CONFIG_I2C_CHARDEV=m CONFIG_I2C_MUX=m @@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y CONFIG_SPI_SLAVE_TIME=m CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m CONFIG_SPI_DYNAMIC=y -CONFIG_SPMI=m +CONFIG_SPMI=y CONFIG_SPMI_HISI3670=m CONFIG_SPMI_MSM_PMIC_ARB=m CONFIG_SPMI_MTK_PMIF=m @@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m CONFIG_PINCTRL_SC7180=m CONFIG_PINCTRL_SC7280=m CONFIG_PINCTRL_SC8180X=m -CONFIG_PINCTRL_SC8280XP=m +CONFIG_PINCTRL_SC8280XP=y # CONFIG_PINCTRL_SDM660 is not set CONFIG_PINCTRL_SDM670=m CONFIG_PINCTRL_SDM845=m @@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m CONFIG_PINCTRL_SM8550=m # CONFIG_PINCTRL_SM8650 is not set # CONFIG_PINCTRL_X1E80100 is not set -CONFIG_PINCTRL_QCOM_SPMI_PMIC=m +CONFIG_PINCTRL_QCOM_SPMI_PMIC=y CONFIG_PINCTRL_QCOM_SSBI_PMIC=m CONFIG_PINCTRL_LPASS_LPI=m # CONFIG_PINCTRL_SC7280_LPASS_LPI is not set @@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y # CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set # CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set # CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set CONFIG_THERMAL_GOV_FAIR_SHARE=y CONFIG_THERMAL_GOV_STEP_WISE=y CONFIG_THERMAL_GOV_BANG_BANG=y CONFIG_THERMAL_GOV_USER_SPACE=y -# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y CONFIG_CPU_THERMAL=y CONFIG_CPU_FREQ_THERMAL=y # CONFIG_CPU_IDLE_THERMAL is not set @@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m # CONFIG_QCOM_TSENS=m CONFIG_QCOM_SPMI_ADC_TM5=m -# CONFIG_QCOM_SPMI_TEMP_ALARM is not set +CONFIG_QCOM_SPMI_TEMP_ALARM=m CONFIG_QCOM_LMH=m # end of Qualcomm thermal drivers @@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m CONFIG_ZIIRAVE_WATCHDOG=m CONFIG_MLX_WDT=m CONFIG_SL28CPLD_WATCHDOG=m -# CONFIG_ARM_SP805_WATCHDOG is not set +CONFIG_ARM_SP805_WATCHDOG=y CONFIG_ARM_SBSA_WATCHDOG=m CONFIG_ARMADA_37XX_WATCHDOG=m CONFIG_CADENCE_WATCHDOG=m @@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m CONFIG_IMX_SC_WDT=m CONFIG_IMX7ULP_WDT=m CONFIG_TEGRA_WATCHDOG=m -# CONFIG_QCOM_WDT is not set +CONFIG_QCOM_WDT=m CONFIG_MESON_GXBB_WATCHDOG=m CONFIG_MESON_WATCHDOG=m CONFIG_MEDIATEK_WATCHDOG=m @@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m CONFIG_SCSI_UFSHCD_PLATFORM=m CONFIG_SCSI_UFS_CDNS_PLATFORM=m # CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set -# CONFIG_SCSI_UFS_QCOM is not set +CONFIG_SCSI_UFS_QCOM=m CONFIG_SCSI_UFS_MEDIATEK=m CONFIG_SCSI_UFS_HISI=m CONFIG_SCSI_UFS_EXYNOS=m @@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m CONFIG_QCS_GCC_404=m CONFIG_SC_CAMCC_7180=m CONFIG_SC_CAMCC_7280=m -# CONFIG_SC_CAMCC_8280XP is not set +CONFIG_SC_CAMCC_8280XP=m CONFIG_SC_DISPCC_7180=m CONFIG_SC_DISPCC_7280=m CONFIG_SC_DISPCC_8280XP=m @@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m CONFIG_SC_GCC_8280XP=m CONFIG_SC_GPUCC_7180=m CONFIG_SC_GPUCC_7280=m -# CONFIG_SC_GPUCC_8280XP is not set +CONFIG_SC_GPUCC_8280XP=m CONFIG_SC_LPASSCC_7280=m -# CONFIG_SC_LPASSCC_8280XP is not set +CONFIG_SC_LPASSCC_8280XP=m CONFIG_SC_LPASS_CORECC_7180=m CONFIG_SC_LPASS_CORECC_7280=m CONFIG_SC_MSS_7180=m @@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m # CONFIG_SM_TCSRCC_8650 is not set CONFIG_SM_VIDEOCC_8150=m CONFIG_SM_VIDEOCC_8250=m -# CONFIG_SM_VIDEOCC_8350 is not set +CONFIG_SM_VIDEOCC_8350=m # CONFIG_SM_VIDEOCC_8550 is not set CONFIG_SPMI_PMIC_CLKDIV=m CONFIG_QCOM_HFPLL=m @@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y # end of Clock Source drivers CONFIG_MAILBOX=y -# CONFIG_ARM_MHU is not set +CONFIG_ARM_MHU=y CONFIG_ARM_MHU_V2=m CONFIG_IMX_MBOX=m CONFIG_PLATFORM_MHU=m @@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y # CONFIG_IOMMU_DEBUGFS is not set # CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set -# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set -CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y +CONFIG_IOMMU_DEFAULT_DMA_LAZY=y +# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set CONFIG_OF_IOMMU=y CONFIG_IOMMU_DMA=y CONFIG_IOMMU_SVA=y @@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m CONFIG_QCOM_KRYO_L2_ACCESSORS=y CONFIG_QCOM_MDT_LOADER=m CONFIG_QCOM_OCMEM=m +CONFIG_QCOM_PD_MAPPER=m CONFIG_QCOM_PDR_HELPERS=m +CONFIG_QCOM_PDR_MSG=m # CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set CONFIG_QCOM_PMIC_GLINK=m CONFIG_QCOM_QMI_HELPERS=m @@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m CONFIG_INTERCONNECT_IMX8MN=m CONFIG_INTERCONNECT_IMX8MQ=m CONFIG_INTERCONNECT_IMX8MP=m -# CONFIG_INTERCONNECT_QCOM is not set +CONFIG_INTERCONNECT_QCOM=y +CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y +# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set +# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set +# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set +# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set +CONFIG_INTERCONNECT_QCOM_OSM_L3=m +# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set +# CONFIG_INTERCONNECT_QCOM_QCS404 is not set +# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set +CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y +CONFIG_INTERCONNECT_QCOM_RPMH=y +# CONFIG_INTERCONNECT_QCOM_SA8775P is not set +# CONFIG_INTERCONNECT_QCOM_SC7180 is not set +# CONFIG_INTERCONNECT_QCOM_SC7280 is not set +# CONFIG_INTERCONNECT_QCOM_SC8180X is not set +CONFIG_INTERCONNECT_QCOM_SC8280XP=y +# CONFIG_INTERCONNECT_QCOM_SDM660 is not set +# CONFIG_INTERCONNECT_QCOM_SDM670 is not set +# CONFIG_INTERCONNECT_QCOM_SDM845 is not set +# CONFIG_INTERCONNECT_QCOM_SDX55 is not set +# CONFIG_INTERCONNECT_QCOM_SDX65 is not set +# CONFIG_INTERCONNECT_QCOM_SDX75 is not set +# CONFIG_INTERCONNECT_QCOM_SM6115 is not set +# CONFIG_INTERCONNECT_QCOM_SM6350 is not set +# CONFIG_INTERCONNECT_QCOM_SM8150 is not set +# CONFIG_INTERCONNECT_QCOM_SM8250 is not set +# CONFIG_INTERCONNECT_QCOM_SM8350 is not set +# CONFIG_INTERCONNECT_QCOM_SM8450 is not set +# CONFIG_INTERCONNECT_QCOM_SM8550 is not set +# CONFIG_INTERCONNECT_QCOM_SM8650 is not set +# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set CONFIG_INTERCONNECT_SAMSUNG=y CONFIG_INTERCONNECT_EXYNOS=m CONFIG_INTERCONNECT_CLK=m diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch new file mode 100644 index 00000000000000..839f0933e411d1 --- /dev/null +++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch @@ -0,0 +1,1964 @@ +source: https://patchwork.kernel.org/project/linux-remoteproc/cover/20240512-qcom-pd-mapper-v8-0-5ecbb276fcc0@linaro.org/ + +From: Dmitry Baryshkov +Date: Sun, 12 May 2024 00:56:03 +0300 +Subject: [PATCH v8 1/5] soc: qcom: pdr: protect locator_addr with the main + mutex + +If the service locator server is restarted fast enough, the PDR can +rewrite locator_addr fields concurrently. Protect them by placing +modification of those fields under the main pdr->lock. + +Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers") +Tested-by: Neil Armstrong # on SM8550-QRD +Tested-by: Steev Klimaszewski +Tested-by: Alexey Minnekhanov +Signed-off-by: Dmitry Baryshkov +--- + drivers/soc/qcom/pdr_interface.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c +index a1b6a4081dea..e014dd2d8ab3 100644 +--- a/drivers/soc/qcom/pdr_interface.c ++++ b/drivers/soc/qcom/pdr_interface.c +@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi, + locator_hdl); + struct pdr_service *pds; + ++ mutex_lock(&pdr->lock); + /* Create a local client port for QMI communication */ + pdr->locator_addr.sq_family = AF_QIPCRTR; + pdr->locator_addr.sq_node = svc->node; + pdr->locator_addr.sq_port = svc->port; + +- mutex_lock(&pdr->lock); + pdr->locator_init_complete = true; + mutex_unlock(&pdr->lock); + +@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi, + + mutex_lock(&pdr->lock); + pdr->locator_init_complete = false; +- mutex_unlock(&pdr->lock); + + pdr->locator_addr.sq_node = 0; + pdr->locator_addr.sq_port = 0; ++ mutex_unlock(&pdr->lock); + } + + static const struct qmi_ops pdr_locator_ops = { +@@ -365,6 +365,7 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req, + if (ret < 0) + return ret; + ++ mutex_lock(&pdr->lock); + ret = qmi_send_request(&pdr->locator_hdl, + &pdr->locator_addr, + &txn, SERVREG_GET_DOMAIN_LIST_REQ, +@@ -373,15 +374,16 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req, + req); + if (ret < 0) { + qmi_txn_cancel(&txn); +- return ret; ++ goto err_unlock; + } + + ret = qmi_txn_wait(&txn, 5 * HZ); + if (ret < 0) { + pr_err("PDR: %s get domain list txn wait failed: %d\n", + req->service_name, ret); +- return ret; ++ goto err_unlock; + } ++ mutex_unlock(&pdr->lock); + + if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { + pr_err("PDR: %s get domain list failed: 0x%x\n", +@@ -390,6 +392,11 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req, + } + + return 0; ++ ++err_unlock: ++ mutex_unlock(&pdr->lock); ++ ++ return ret; + } + + static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds) + +From: Dmitry Baryshkov +Date: Sun, 12 May 2024 00:56:04 +0300 +Subject: [PATCH v8 2/5] soc: qcom: pdr: fix parsing of domains lists + +While parsing the domains list, start offsets from 0 rather than from +domains_read. The domains_read is equal to the total count of the +domains we have seen, while the domains list in the message starts from +offset 0. + +Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers") +Tested-by: Steev Klimaszewski +Tested-by: Alexey Minnekhanov +Signed-off-by: Dmitry Baryshkov +--- + drivers/soc/qcom/pdr_interface.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c +index e014dd2d8ab3..d495ee736519 100644 +--- a/drivers/soc/qcom/pdr_interface.c ++++ b/drivers/soc/qcom/pdr_interface.c +@@ -422,7 +422,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds) + if (ret < 0) + goto out; + +- for (i = domains_read; i < resp->domain_list_len; i++) { ++ for (i = 0; i < resp->domain_list_len; i++) { + entry = &resp->domain_list[i]; + + if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name)) + +From: Dmitry Baryshkov +Date: Sun, 12 May 2024 00:56:05 +0300 +Subject: [PATCH v8 3/5] soc: qcom: pdr: extract PDR message marshalling + data + +The in-kernel PD mapper is going to use same message structures as the +QCOM_PDR_HELPERS module. Extract message marshalling data to separate +module that can be used by both PDR helpers and by PD mapper. + +Reviewed-by: Bryan O'Donoghue +Tested-by: Steev Klimaszewski +Tested-by: Alexey Minnekhanov +Signed-off-by: Dmitry Baryshkov +--- + drivers/soc/qcom/Kconfig | 4 + + drivers/soc/qcom/Makefile | 1 + + drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------ + drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 334 insertions(+), 296 deletions(-) + +diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig +index 5af33b0e3470..95973c6b828f 100644 +--- a/drivers/soc/qcom/Kconfig ++++ b/drivers/soc/qcom/Kconfig +@@ -75,8 +75,12 @@ config QCOM_OCMEM + config QCOM_PDR_HELPERS + tristate + select QCOM_QMI_HELPERS ++ select QCOM_PDR_MSG + depends on NET + ++config QCOM_PDR_MSG ++ tristate ++ + config QCOM_PMIC_PDCHARGER_ULOG + tristate "Qualcomm PMIC PDCharger ULOG driver" + depends on RPMSG +diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile +index ca0bece0dfff..3110ac3288bc 100644 +--- a/drivers/soc/qcom/Makefile ++++ b/drivers/soc/qcom/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o + obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o + obj-$(CONFIG_QCOM_OCMEM) += ocmem.o + obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o ++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o + obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o + obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o + obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o +diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h +index 03c282b7f17e..7e5bb5a95275 100644 +--- a/drivers/soc/qcom/pdr_internal.h ++++ b/drivers/soc/qcom/pdr_internal.h +@@ -28,83 +28,12 @@ struct servreg_location_entry { + u32 instance; + }; + +-static const struct qmi_elem_info servreg_location_entry_ei[] = { +- { +- .data_type = QMI_STRING, +- .elem_len = SERVREG_NAME_LENGTH + 1, +- .elem_size = sizeof(char), +- .array_type = NO_ARRAY, +- .tlv_type = 0, +- .offset = offsetof(struct servreg_location_entry, +- name), +- }, +- { +- .data_type = QMI_UNSIGNED_4_BYTE, +- .elem_len = 1, +- .elem_size = sizeof(u32), +- .array_type = NO_ARRAY, +- .tlv_type = 0, +- .offset = offsetof(struct servreg_location_entry, +- instance), +- }, +- { +- .data_type = QMI_UNSIGNED_1_BYTE, +- .elem_len = 1, +- .elem_size = sizeof(u8), +- .array_type = NO_ARRAY, +- .tlv_type = 0, +- .offset = offsetof(struct servreg_location_entry, +- service_data_valid), +- }, +- { +- .data_type = QMI_UNSIGNED_4_BYTE, +- .elem_len = 1, +- .elem_size = sizeof(u32), +- .array_type = NO_ARRAY, +- .tlv_type = 0, +- .offset = offsetof(struct servreg_location_entry, +- service_data), +- }, +- {} +-}; +- + struct servreg_get_domain_list_req { + char service_name[SERVREG_NAME_LENGTH + 1]; + u8 domain_offset_valid; + u32 domain_offset; + }; + +-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = { +- { +- .data_type = QMI_STRING, +- .elem_len = SERVREG_NAME_LENGTH + 1, +- .elem_size = sizeof(char), +- .array_type = NO_ARRAY, +- .tlv_type = 0x01, +- .offset = offsetof(struct servreg_get_domain_list_req, +- service_name), +- }, +- { +- .data_type = QMI_OPT_FLAG, +- .elem_len = 1, +- .elem_size = sizeof(u8), +- .array_type = NO_ARRAY, +- .tlv_type = 0x10, +- .offset = offsetof(struct servreg_get_domain_list_req, +- domain_offset_valid), +- }, +- { +- .data_type = QMI_UNSIGNED_4_BYTE, +- .elem_len = 1, +- .elem_size = sizeof(u32), +- .array_type = NO_ARRAY, +- .tlv_type = 0x10, +- .offset = offsetof(struct servreg_get_domain_list_req, +- domain_offset), +- }, +- {} +-}; +- + struct servreg_get_domain_list_resp { + struct qmi_response_type_v01 resp; + u8 total_domains_valid; +@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp { + struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH]; + }; + +-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = { +- { +- .data_type = QMI_STRUCT, +- .elem_len = 1, +- .elem_size = sizeof(struct qmi_response_type_v01), +- .array_type = NO_ARRAY, +- .tlv_type = 0x02, +- .offset = offsetof(struct servreg_get_domain_list_resp, +- resp), +- .ei_array = qmi_response_type_v01_ei, +- }, +- { +- .data_type = QMI_OPT_FLAG, +- .elem_len = 1, +- .elem_size = sizeof(u8), +- .array_type = NO_ARRAY, +- .tlv_type = 0x10, +- .offset = offsetof(struct servreg_get_domain_list_resp, +- total_domains_valid), +- }, +- { +- .data_type = QMI_UNSIGNED_2_BYTE, +- .elem_len = 1, +- .elem_size = sizeof(u16), +- .array_type = NO_ARRAY, +- .tlv_type = 0x10, +- .offset = offsetof(struct servreg_get_domain_list_resp, +- total_domains), +- }, +- { +- .data_type = QMI_OPT_FLAG, +- .elem_len = 1, +- .elem_size = sizeof(u8), +- .array_type = NO_ARRAY, +- .tlv_type = 0x11, +- .offset = offsetof(struct servreg_get_domain_list_resp, +- db_rev_count_valid), +- }, +- { +- .data_type = QMI_UNSIGNED_2_BYTE, +- .elem_len = 1, +- .elem_size = sizeof(u16), +- .array_type = NO_ARRAY, +- .tlv_type = 0x11, +- .offset = offsetof(struct servreg_get_domain_list_resp, +- db_rev_count), +- }, +- { +- .data_type = QMI_OPT_FLAG, +- .elem_len = 1, +- .elem_size = sizeof(u8), +- .array_type = NO_ARRAY, +- .tlv_type = 0x12, +- .offset = offsetof(struct servreg_get_domain_list_resp, +- domain_list_valid), +- }, +- { +- .data_type = QMI_DATA_LEN, +- .elem_len = 1, +- .elem_size = sizeof(u8), +- .array_type = NO_ARRAY, +- .tlv_type = 0x12, +- .offset = offsetof(struct servreg_get_domain_list_resp, +- domain_list_len), +- }, +- { +- .data_type = QMI_STRUCT, +- .elem_len = SERVREG_DOMAIN_LIST_LENGTH, +- .elem_size = sizeof(struct servreg_location_entry), +- .array_type = VAR_LEN_ARRAY, +- .tlv_type = 0x12, +- .offset = offsetof(struct servreg_get_domain_list_resp, +- domain_list), +- .ei_array = servreg_location_entry_ei, +- }, +- {} +-}; +- + struct servreg_register_listener_req { + u8 enable; + char service_path[SERVREG_NAME_LENGTH + 1]; + }; + +-static const struct qmi_elem_info servreg_register_listener_req_ei[] = { +- { +- .data_type = QMI_UNSIGNED_1_BYTE, +- .elem_len = 1, +- .elem_size = sizeof(u8), +- .array_type = NO_ARRAY, +- .tlv_type = 0x01, +- .offset = offsetof(struct servreg_register_listener_req, +- enable), +- }, +- { +- .data_type = QMI_STRING, +- .elem_len = SERVREG_NAME_LENGTH + 1, +- .elem_size = sizeof(char), +- .array_type = NO_ARRAY, +- .tlv_type = 0x02, +- .offset = offsetof(struct servreg_register_listener_req, +- service_path), +- }, +- {} +-}; +- + struct servreg_register_listener_resp { + struct qmi_response_type_v01 resp; + u8 curr_state_valid; + enum servreg_service_state curr_state; + }; + +-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = { +- { +- .data_type = QMI_STRUCT, +- .elem_len = 1, +- .elem_size = sizeof(struct qmi_response_type_v01), +- .array_type = NO_ARRAY, +- .tlv_type = 0x02, +- .offset = offsetof(struct servreg_register_listener_resp, +- resp), +- .ei_array = qmi_response_type_v01_ei, +- }, +- { +- .data_type = QMI_OPT_FLAG, +- .elem_len = 1, +- .elem_size = sizeof(u8), +- .array_type = NO_ARRAY, +- .tlv_type = 0x10, +- .offset = offsetof(struct servreg_register_listener_resp, +- curr_state_valid), +- }, +- { +- .data_type = QMI_SIGNED_4_BYTE_ENUM, +- .elem_len = 1, +- .elem_size = sizeof(enum servreg_service_state), +- .array_type = NO_ARRAY, +- .tlv_type = 0x10, +- .offset = offsetof(struct servreg_register_listener_resp, +- curr_state), +- }, +- {} +-}; +- + struct servreg_restart_pd_req { + char service_path[SERVREG_NAME_LENGTH + 1]; + }; + +-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = { +- { +- .data_type = QMI_STRING, +- .elem_len = SERVREG_NAME_LENGTH + 1, +- .elem_size = sizeof(char), +- .array_type = NO_ARRAY, +- .tlv_type = 0x01, +- .offset = offsetof(struct servreg_restart_pd_req, +- service_path), +- }, +- {} +-}; +- + struct servreg_restart_pd_resp { + struct qmi_response_type_v01 resp; + }; + +-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = { +- { +- .data_type = QMI_STRUCT, +- .elem_len = 1, +- .elem_size = sizeof(struct qmi_response_type_v01), +- .array_type = NO_ARRAY, +- .tlv_type = 0x02, +- .offset = offsetof(struct servreg_restart_pd_resp, +- resp), +- .ei_array = qmi_response_type_v01_ei, +- }, +- {} +-}; +- + struct servreg_state_updated_ind { + enum servreg_service_state curr_state; + char service_path[SERVREG_NAME_LENGTH + 1]; + u16 transaction_id; + }; + +-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = { +- { +- .data_type = QMI_SIGNED_4_BYTE_ENUM, +- .elem_len = 1, +- .elem_size = sizeof(u32), +- .array_type = NO_ARRAY, +- .tlv_type = 0x01, +- .offset = offsetof(struct servreg_state_updated_ind, +- curr_state), +- }, +- { +- .data_type = QMI_STRING, +- .elem_len = SERVREG_NAME_LENGTH + 1, +- .elem_size = sizeof(char), +- .array_type = NO_ARRAY, +- .tlv_type = 0x02, +- .offset = offsetof(struct servreg_state_updated_ind, +- service_path), +- }, +- { +- .data_type = QMI_UNSIGNED_2_BYTE, +- .elem_len = 1, +- .elem_size = sizeof(u16), +- .array_type = NO_ARRAY, +- .tlv_type = 0x03, +- .offset = offsetof(struct servreg_state_updated_ind, +- transaction_id), +- }, +- {} +-}; +- + struct servreg_set_ack_req { + char service_path[SERVREG_NAME_LENGTH + 1]; + u16 transaction_id; + }; + +-static const struct qmi_elem_info servreg_set_ack_req_ei[] = { +- { +- .data_type = QMI_STRING, +- .elem_len = SERVREG_NAME_LENGTH + 1, +- .elem_size = sizeof(char), +- .array_type = NO_ARRAY, +- .tlv_type = 0x01, +- .offset = offsetof(struct servreg_set_ack_req, +- service_path), +- }, +- { +- .data_type = QMI_UNSIGNED_2_BYTE, +- .elem_len = 1, +- .elem_size = sizeof(u16), +- .array_type = NO_ARRAY, +- .tlv_type = 0x02, +- .offset = offsetof(struct servreg_set_ack_req, +- transaction_id), +- }, +- {} +-}; +- + struct servreg_set_ack_resp { + struct qmi_response_type_v01 resp; + }; + +-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = { +- { +- .data_type = QMI_STRUCT, +- .elem_len = 1, +- .elem_size = sizeof(struct qmi_response_type_v01), +- .array_type = NO_ARRAY, +- .tlv_type = 0x02, +- .offset = offsetof(struct servreg_set_ack_resp, +- resp), +- .ei_array = qmi_response_type_v01_ei, +- }, +- {} +-}; ++extern const struct qmi_elem_info servreg_location_entry_ei[]; ++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[]; ++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[]; ++extern const struct qmi_elem_info servreg_register_listener_req_ei[]; ++extern const struct qmi_elem_info servreg_register_listener_resp_ei[]; ++extern const struct qmi_elem_info servreg_restart_pd_req_ei[]; ++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[]; ++extern const struct qmi_elem_info servreg_state_updated_ind_ei[]; ++extern const struct qmi_elem_info servreg_set_ack_req_ei[]; ++extern const struct qmi_elem_info servreg_set_ack_resp_ei[]; + + #endif +diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c +new file mode 100644 +index 000000000000..9b46f42aa146 +--- /dev/null ++++ b/drivers/soc/qcom/qcom_pdr_msg.c +@@ -0,0 +1,319 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2020 The Linux Foundation. All rights reserved. ++ */ ++ ++#include ++#include ++ ++#include "pdr_internal.h" ++ ++const struct qmi_elem_info servreg_location_entry_ei[] = { ++ { ++ .data_type = QMI_STRING, ++ .elem_len = SERVREG_NAME_LENGTH + 1, ++ .elem_size = sizeof(char), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0, ++ .offset = offsetof(struct servreg_location_entry, ++ name), ++ }, ++ { ++ .data_type = QMI_UNSIGNED_4_BYTE, ++ .elem_len = 1, ++ .elem_size = sizeof(u32), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0, ++ .offset = offsetof(struct servreg_location_entry, ++ instance), ++ }, ++ { ++ .data_type = QMI_UNSIGNED_1_BYTE, ++ .elem_len = 1, ++ .elem_size = sizeof(u8), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0, ++ .offset = offsetof(struct servreg_location_entry, ++ service_data_valid), ++ }, ++ { ++ .data_type = QMI_UNSIGNED_4_BYTE, ++ .elem_len = 1, ++ .elem_size = sizeof(u32), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0, ++ .offset = offsetof(struct servreg_location_entry, ++ service_data), ++ }, ++ {} ++}; ++EXPORT_SYMBOL_GPL(servreg_location_entry_ei); ++ ++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = { ++ { ++ .data_type = QMI_STRING, ++ .elem_len = SERVREG_NAME_LENGTH + 1, ++ .elem_size = sizeof(char), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x01, ++ .offset = offsetof(struct servreg_get_domain_list_req, ++ service_name), ++ }, ++ { ++ .data_type = QMI_OPT_FLAG, ++ .elem_len = 1, ++ .elem_size = sizeof(u8), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x10, ++ .offset = offsetof(struct servreg_get_domain_list_req, ++ domain_offset_valid), ++ }, ++ { ++ .data_type = QMI_UNSIGNED_4_BYTE, ++ .elem_len = 1, ++ .elem_size = sizeof(u32), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x10, ++ .offset = offsetof(struct servreg_get_domain_list_req, ++ domain_offset), ++ }, ++ {} ++}; ++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei); ++ ++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = { ++ { ++ .data_type = QMI_STRUCT, ++ .elem_len = 1, ++ .elem_size = sizeof(struct qmi_response_type_v01), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x02, ++ .offset = offsetof(struct servreg_get_domain_list_resp, ++ resp), ++ .ei_array = qmi_response_type_v01_ei, ++ }, ++ { ++ .data_type = QMI_OPT_FLAG, ++ .elem_len = 1, ++ .elem_size = sizeof(u8), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x10, ++ .offset = offsetof(struct servreg_get_domain_list_resp, ++ total_domains_valid), ++ }, ++ { ++ .data_type = QMI_UNSIGNED_2_BYTE, ++ .elem_len = 1, ++ .elem_size = sizeof(u16), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x10, ++ .offset = offsetof(struct servreg_get_domain_list_resp, ++ total_domains), ++ }, ++ { ++ .data_type = QMI_OPT_FLAG, ++ .elem_len = 1, ++ .elem_size = sizeof(u8), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x11, ++ .offset = offsetof(struct servreg_get_domain_list_resp, ++ db_rev_count_valid), ++ }, ++ { ++ .data_type = QMI_UNSIGNED_2_BYTE, ++ .elem_len = 1, ++ .elem_size = sizeof(u16), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x11, ++ .offset = offsetof(struct servreg_get_domain_list_resp, ++ db_rev_count), ++ }, ++ { ++ .data_type = QMI_OPT_FLAG, ++ .elem_len = 1, ++ .elem_size = sizeof(u8), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x12, ++ .offset = offsetof(struct servreg_get_domain_list_resp, ++ domain_list_valid), ++ }, ++ { ++ .data_type = QMI_DATA_LEN, ++ .elem_len = 1, ++ .elem_size = sizeof(u8), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x12, ++ .offset = offsetof(struct servreg_get_domain_list_resp, ++ domain_list_len), ++ }, ++ { ++ .data_type = QMI_STRUCT, ++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH, ++ .elem_size = sizeof(struct servreg_location_entry), ++ .array_type = VAR_LEN_ARRAY, ++ .tlv_type = 0x12, ++ .offset = offsetof(struct servreg_get_domain_list_resp, ++ domain_list), ++ .ei_array = servreg_location_entry_ei, ++ }, ++ {} ++}; ++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei); ++ ++const struct qmi_elem_info servreg_register_listener_req_ei[] = { ++ { ++ .data_type = QMI_UNSIGNED_1_BYTE, ++ .elem_len = 1, ++ .elem_size = sizeof(u8), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x01, ++ .offset = offsetof(struct servreg_register_listener_req, ++ enable), ++ }, ++ { ++ .data_type = QMI_STRING, ++ .elem_len = SERVREG_NAME_LENGTH + 1, ++ .elem_size = sizeof(char), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x02, ++ .offset = offsetof(struct servreg_register_listener_req, ++ service_path), ++ }, ++ {} ++}; ++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei); ++ ++const struct qmi_elem_info servreg_register_listener_resp_ei[] = { ++ { ++ .data_type = QMI_STRUCT, ++ .elem_len = 1, ++ .elem_size = sizeof(struct qmi_response_type_v01), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x02, ++ .offset = offsetof(struct servreg_register_listener_resp, ++ resp), ++ .ei_array = qmi_response_type_v01_ei, ++ }, ++ { ++ .data_type = QMI_OPT_FLAG, ++ .elem_len = 1, ++ .elem_size = sizeof(u8), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x10, ++ .offset = offsetof(struct servreg_register_listener_resp, ++ curr_state_valid), ++ }, ++ { ++ .data_type = QMI_SIGNED_4_BYTE_ENUM, ++ .elem_len = 1, ++ .elem_size = sizeof(enum servreg_service_state), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x10, ++ .offset = offsetof(struct servreg_register_listener_resp, ++ curr_state), ++ }, ++ {} ++}; ++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei); ++ ++const struct qmi_elem_info servreg_restart_pd_req_ei[] = { ++ { ++ .data_type = QMI_STRING, ++ .elem_len = SERVREG_NAME_LENGTH + 1, ++ .elem_size = sizeof(char), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x01, ++ .offset = offsetof(struct servreg_restart_pd_req, ++ service_path), ++ }, ++ {} ++}; ++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei); ++ ++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = { ++ { ++ .data_type = QMI_STRUCT, ++ .elem_len = 1, ++ .elem_size = sizeof(struct qmi_response_type_v01), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x02, ++ .offset = offsetof(struct servreg_restart_pd_resp, ++ resp), ++ .ei_array = qmi_response_type_v01_ei, ++ }, ++ {} ++}; ++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei); ++ ++const struct qmi_elem_info servreg_state_updated_ind_ei[] = { ++ { ++ .data_type = QMI_SIGNED_4_BYTE_ENUM, ++ .elem_len = 1, ++ .elem_size = sizeof(u32), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x01, ++ .offset = offsetof(struct servreg_state_updated_ind, ++ curr_state), ++ }, ++ { ++ .data_type = QMI_STRING, ++ .elem_len = SERVREG_NAME_LENGTH + 1, ++ .elem_size = sizeof(char), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x02, ++ .offset = offsetof(struct servreg_state_updated_ind, ++ service_path), ++ }, ++ { ++ .data_type = QMI_UNSIGNED_2_BYTE, ++ .elem_len = 1, ++ .elem_size = sizeof(u16), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x03, ++ .offset = offsetof(struct servreg_state_updated_ind, ++ transaction_id), ++ }, ++ {} ++}; ++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei); ++ ++const struct qmi_elem_info servreg_set_ack_req_ei[] = { ++ { ++ .data_type = QMI_STRING, ++ .elem_len = SERVREG_NAME_LENGTH + 1, ++ .elem_size = sizeof(char), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x01, ++ .offset = offsetof(struct servreg_set_ack_req, ++ service_path), ++ }, ++ { ++ .data_type = QMI_UNSIGNED_2_BYTE, ++ .elem_len = 1, ++ .elem_size = sizeof(u16), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x02, ++ .offset = offsetof(struct servreg_set_ack_req, ++ transaction_id), ++ }, ++ {} ++}; ++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei); ++ ++const struct qmi_elem_info servreg_set_ack_resp_ei[] = { ++ { ++ .data_type = QMI_STRUCT, ++ .elem_len = 1, ++ .elem_size = sizeof(struct qmi_response_type_v01), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x02, ++ .offset = offsetof(struct servreg_set_ack_resp, ++ resp), ++ .ei_array = qmi_response_type_v01_ei, ++ }, ++ {} ++}; ++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data"); + +From: Dmitry Baryshkov +Date: Sun, 12 May 2024 00:56:06 +0300 +Subject: [PATCH v8 4/5] soc: qcom: add pd-mapper implementation + +Existing userspace protection domain mapper implementation has several +issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't +reread JSON files if firmware location is changed (or if firmware was +not available at the time pd-mapper was started but the corresponding +directory is mounted later), etc. + +Provide in-kernel service implementing protection domain mapping +required to work with several services, which are provided by the DSP +firmware. + +This module is loaded automatically by the remoteproc drivers when +necessary via the symbol dependency. It uses a root node to match a +protection domains map for a particular board. It is not possible to +implement it as a 'driver' as there is no corresponding device. + +Tested-by: Steev Klimaszewski +Tested-by: Alexey Minnekhanov +Signed-off-by: Dmitry Baryshkov +--- + drivers/soc/qcom/Kconfig | 11 + + drivers/soc/qcom/Makefile | 1 + + drivers/soc/qcom/pdr_internal.h | 14 + + drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++ + drivers/soc/qcom/qcom_pdr_msg.c | 34 ++ + 5 files changed, 736 insertions(+) + +diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig +index 95973c6b828f..0a2f2bfd7863 100644 +--- a/drivers/soc/qcom/Kconfig ++++ b/drivers/soc/qcom/Kconfig +@@ -72,6 +72,17 @@ config QCOM_OCMEM + requirements. This is typically used by the GPU, camera/video, and + audio components on some Snapdragon SoCs. + ++config QCOM_PD_MAPPER ++ tristate "Qualcomm Protection Domain Mapper" ++ select QCOM_QMI_HELPERS ++ depends on NET && QRTR ++ default QCOM_RPROC_COMMON ++ help ++ The Protection Domain Mapper maps registered services to the domains ++ and instances handled by the remote DSPs. This is a kernel-space ++ implementation of the service. It is a simpler alternative to the ++ userspace daemon. ++ + config QCOM_PDR_HELPERS + tristate + select QCOM_QMI_HELPERS +diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile +index 3110ac3288bc..d3560f861085 100644 +--- a/drivers/soc/qcom/Makefile ++++ b/drivers/soc/qcom/Makefile +@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o + obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o + obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o + obj-$(CONFIG_QCOM_OCMEM) += ocmem.o ++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o + obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o + obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o + obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o +diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h +index 7e5bb5a95275..8d17f7fb79e7 100644 +--- a/drivers/soc/qcom/pdr_internal.h ++++ b/drivers/soc/qcom/pdr_internal.h +@@ -13,6 +13,8 @@ + #define SERVREG_SET_ACK_REQ 0x23 + #define SERVREG_RESTART_PD_REQ 0x24 + ++#define SERVREG_LOC_PFR_REQ 0x24 ++ + #define SERVREG_DOMAIN_LIST_LENGTH 32 + #define SERVREG_RESTART_PD_REQ_MAX_LEN 67 + #define SERVREG_REGISTER_LISTENER_REQ_LEN 71 +@@ -20,6 +22,7 @@ + #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74 + #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79 + #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389 ++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10 + + struct servreg_location_entry { + char name[SERVREG_NAME_LENGTH + 1]; +@@ -79,6 +82,15 @@ struct servreg_set_ack_resp { + struct qmi_response_type_v01 resp; + }; + ++struct servreg_loc_pfr_req { ++ char service[SERVREG_NAME_LENGTH + 1]; ++ char reason[257]; ++}; ++ ++struct servreg_loc_pfr_resp { ++ struct qmi_response_type_v01 rsp; ++}; ++ + extern const struct qmi_elem_info servreg_location_entry_ei[]; + extern const struct qmi_elem_info servreg_get_domain_list_req_ei[]; + extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[]; +@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[]; + extern const struct qmi_elem_info servreg_state_updated_ind_ei[]; + extern const struct qmi_elem_info servreg_set_ack_req_ei[]; + extern const struct qmi_elem_info servreg_set_ack_resp_ei[]; ++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[]; ++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[]; + + #endif +diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c +new file mode 100644 +index 000000000000..ecb64f06527f +--- /dev/null ++++ b/drivers/soc/qcom/qcom_pd_mapper.c +@@ -0,0 +1,676 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Qualcomm Protection Domain mapper ++ * ++ * Copyright (c) 2023 Linaro Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "pdr_internal.h" ++ ++#define SERVREG_QMI_VERSION 0x101 ++#define SERVREG_QMI_INSTANCE 0 ++ ++#define TMS_SERVREG_SERVICE "tms/servreg" ++ ++struct qcom_pdm_domain_data { ++ const char *domain; ++ u32 instance_id; ++ /* NULL-terminated array */ ++ const char * services[]; ++}; ++ ++struct qcom_pdm_domain { ++ struct list_head list; ++ const char *name; ++ u32 instance_id; ++}; ++ ++struct qcom_pdm_service { ++ struct list_head list; ++ struct list_head domains; ++ const char *name; ++}; ++ ++struct qcom_pdm_data { ++ refcount_t refcnt; ++ struct qmi_handle handle; ++ struct list_head services; ++}; ++ ++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */ ++static struct qcom_pdm_data *__qcom_pdm_data; ++ ++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data, ++ const char *name) ++{ ++ struct qcom_pdm_service *service; ++ ++ list_for_each_entry(service, &data->services, list) { ++ if (!strcmp(service->name, name)) ++ return service; ++ } ++ ++ return NULL; ++} ++ ++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data, ++ const char *service_name, ++ const char *domain_name, ++ u32 instance_id) ++{ ++ struct qcom_pdm_service *service; ++ struct qcom_pdm_domain *domain; ++ ++ service = qcom_pdm_find(data, service_name); ++ if (service) { ++ list_for_each_entry(domain, &service->domains, list) { ++ if (!strcmp(domain->name, domain_name)) ++ return -EBUSY; ++ } ++ } else { ++ service = kzalloc(sizeof(*service), GFP_KERNEL); ++ if (!service) ++ return -ENOMEM; ++ ++ INIT_LIST_HEAD(&service->domains); ++ service->name = service_name; ++ ++ list_add_tail(&service->list, &data->services); ++ } ++ ++ domain = kzalloc(sizeof(*domain), GFP_KERNEL); ++ if (!domain) { ++ if (list_empty(&service->domains)) { ++ list_del(&service->list); ++ kfree(service); ++ } ++ ++ return -ENOMEM; ++ } ++ ++ domain->name = domain_name; ++ domain->instance_id = instance_id; ++ list_add_tail(&domain->list, &service->domains); ++ ++ return 0; ++} ++ ++static int qcom_pdm_add_domain(struct qcom_pdm_data *data, ++ const struct qcom_pdm_domain_data *domain) ++{ ++ int ret; ++ int i; ++ ++ ret = qcom_pdm_add_service_domain(data, ++ TMS_SERVREG_SERVICE, ++ domain->domain, ++ domain->instance_id); ++ if (ret) ++ return ret; ++ ++ for (i = 0; domain->services[i]; i++) { ++ ret = qcom_pdm_add_service_domain(data, ++ domain->services[i], ++ domain->domain, ++ domain->instance_id); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++ ++} ++ ++static void qcom_pdm_free_domains(struct qcom_pdm_data *data) ++{ ++ struct qcom_pdm_service *service, *tservice; ++ struct qcom_pdm_domain *domain, *tdomain; ++ ++ list_for_each_entry_safe(service, tservice, &data->services, list) { ++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) { ++ list_del(&domain->list); ++ kfree(domain); ++ } ++ ++ list_del(&service->list); ++ kfree(service); ++ } ++} ++ ++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi, ++ struct sockaddr_qrtr *sq, ++ struct qmi_txn *txn, ++ const void *decoded) ++{ ++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle); ++ const struct servreg_get_domain_list_req *req = decoded; ++ struct servreg_get_domain_list_resp *rsp; ++ struct qcom_pdm_service *service; ++ u32 offset; ++ int ret; ++ ++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL); ++ if (!rsp) ++ return; ++ ++ offset = req->domain_offset_valid ? req->domain_offset : 0; ++ ++ rsp->resp.result = QMI_RESULT_SUCCESS_V01; ++ rsp->resp.error = QMI_ERR_NONE_V01; ++ ++ rsp->db_rev_count_valid = true; ++ rsp->db_rev_count = 1; ++ ++ rsp->total_domains_valid = true; ++ rsp->total_domains = 0; ++ ++ mutex_lock(&qcom_pdm_mutex); ++ ++ service = qcom_pdm_find(data, req->service_name); ++ if (service) { ++ struct qcom_pdm_domain *domain; ++ ++ rsp->domain_list_valid = true; ++ rsp->domain_list_len = 0; ++ ++ list_for_each_entry(domain, &service->domains, list) { ++ u32 i = rsp->total_domains++; ++ ++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) { ++ u32 j = rsp->domain_list_len++; ++ ++ strscpy(rsp->domain_list[j].name, domain->name, ++ sizeof(rsp->domain_list[i].name)); ++ rsp->domain_list[j].instance = domain->instance_id; ++ ++ pr_debug("PDM: found %s / %d\n", domain->name, ++ domain->instance_id); ++ } ++ } ++ } ++ ++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name, ++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains); ++ ++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ, ++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN, ++ servreg_get_domain_list_resp_ei, rsp); ++ if (ret) ++ pr_err("Error sending servreg response: %d\n", ret); ++ ++ mutex_unlock(&qcom_pdm_mutex); ++ ++ kfree(rsp); ++} ++ ++static void qcom_pdm_pfr(struct qmi_handle *qmi, ++ struct sockaddr_qrtr *sq, ++ struct qmi_txn *txn, ++ const void *decoded) ++{ ++ const struct servreg_loc_pfr_req *req = decoded; ++ struct servreg_loc_pfr_resp rsp = {}; ++ int ret; ++ ++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason); ++ ++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01; ++ rsp.rsp.error = QMI_ERR_NONE_V01; ++ ++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ, ++ SERVREG_LOC_PFR_RESP_MAX_LEN, ++ servreg_loc_pfr_resp_ei, &rsp); ++ if (ret) ++ pr_err("Error sending servreg response: %d\n", ret); ++} ++ ++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = { ++ { ++ .type = QMI_REQUEST, ++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ, ++ .ei = servreg_get_domain_list_req_ei, ++ .decoded_size = sizeof(struct servreg_get_domain_list_req), ++ .fn = qcom_pdm_get_domain_list, ++ }, ++ { ++ .type = QMI_REQUEST, ++ .msg_id = SERVREG_LOC_PFR_REQ, ++ .ei = servreg_loc_pfr_req_ei, ++ .decoded_size = sizeof(struct servreg_loc_pfr_req), ++ .fn = qcom_pdm_pfr, ++ }, ++ { }, ++}; ++ ++static const struct qcom_pdm_domain_data adsp_audio_pd = { ++ .domain = "msm/adsp/audio_pd", ++ .instance_id = 74, ++ .services = { ++ "avs/audio", ++ NULL, ++ }, ++}; ++ ++static const struct qcom_pdm_domain_data adsp_charger_pd = { ++ .domain = "msm/adsp/charger_pd", ++ .instance_id = 74, ++ .services = { NULL }, ++}; ++ ++static const struct qcom_pdm_domain_data adsp_root_pd = { ++ .domain = "msm/adsp/root_pd", ++ .instance_id = 74, ++ .services = { NULL }, ++}; ++ ++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = { ++ .domain = "msm/adsp/root_pd", ++ .instance_id = 74, ++ .services = { ++ "tms/pdr_enabled", ++ NULL, ++ }, ++}; ++ ++static const struct qcom_pdm_domain_data adsp_sensor_pd = { ++ .domain = "msm/adsp/sensor_pd", ++ .instance_id = 74, ++ .services = { NULL }, ++}; ++ ++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = { ++ .domain = "msm/adsp/audio_pd", ++ .instance_id = 4, ++ .services = { NULL }, ++}; ++ ++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = { ++ .domain = "msm/adsp/root_pd", ++ .instance_id = 4, ++ .services = { NULL }, ++}; ++ ++static const struct qcom_pdm_domain_data cdsp_root_pd = { ++ .domain = "msm/cdsp/root_pd", ++ .instance_id = 76, ++ .services = { NULL }, ++}; ++ ++static const struct qcom_pdm_domain_data slpi_root_pd = { ++ .domain = "msm/slpi/root_pd", ++ .instance_id = 90, ++ .services = { NULL }, ++}; ++ ++static const struct qcom_pdm_domain_data slpi_sensor_pd = { ++ .domain = "msm/slpi/sensor_pd", ++ .instance_id = 90, ++ .services = { NULL }, ++}; ++ ++static const struct qcom_pdm_domain_data mpss_root_pd = { ++ .domain = "msm/modem/root_pd", ++ .instance_id = 180, ++ .services = { ++ NULL, ++ }, ++}; ++ ++static const struct qcom_pdm_domain_data mpss_root_pd_gps = { ++ .domain = "msm/modem/root_pd", ++ .instance_id = 180, ++ .services = { ++ "gps/gps_service", ++ NULL, ++ }, ++}; ++ ++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = { ++ .domain = "msm/modem/root_pd", ++ .instance_id = 180, ++ .services = { ++ "gps/gps_service", ++ "tms/pdr_enabled", ++ NULL, ++ }, ++}; ++ ++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = { ++ .domain = "msm/modem/root_pd", ++ .instance_id = 100, ++ .services = { NULL }, ++}; ++ ++static const struct qcom_pdm_domain_data mpss_wlan_pd = { ++ .domain = "msm/modem/wlan_pd", ++ .instance_id = 180, ++ .services = { ++ "kernel/elf_loader", ++ "wlan/fw", ++ NULL, ++ }, ++}; ++ ++static const struct qcom_pdm_domain_data *msm8996_domains[] = { ++ &msm8996_adsp_audio_pd, ++ &msm8996_adsp_root_pd, ++ &msm8996_mpss_root_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *msm8998_domains[] = { ++ &mpss_root_pd, ++ &mpss_wlan_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *qcm2290_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd, ++ &adsp_sensor_pd, ++ &mpss_root_pd_gps, ++ &mpss_wlan_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *qcs404_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd, ++ &adsp_sensor_pd, ++ &cdsp_root_pd, ++ &mpss_root_pd, ++ &mpss_wlan_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *sc7180_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd_pdr, ++ &adsp_sensor_pd, ++ &mpss_root_pd_gps_pdr, ++ &mpss_wlan_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *sc7280_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd_pdr, ++ &adsp_charger_pd, ++ &adsp_sensor_pd, ++ &cdsp_root_pd, ++ &mpss_root_pd_gps_pdr, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *sc8180x_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd, ++ &adsp_charger_pd, ++ &cdsp_root_pd, ++ &mpss_root_pd_gps, ++ &mpss_wlan_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd_pdr, ++ &adsp_charger_pd, ++ &cdsp_root_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *sdm660_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd, ++ &adsp_sensor_pd, ++ &cdsp_root_pd, ++ &mpss_root_pd, ++ &mpss_wlan_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *sdm670_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd, ++ &cdsp_root_pd, ++ &mpss_root_pd, ++ &mpss_wlan_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *sdm845_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd, ++ &cdsp_root_pd, ++ &mpss_root_pd, ++ &mpss_wlan_pd, ++ &slpi_root_pd, ++ &slpi_sensor_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *sm6115_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd, ++ &adsp_sensor_pd, ++ &cdsp_root_pd, ++ &mpss_root_pd_gps, ++ &mpss_wlan_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *sm6350_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd, ++ &adsp_sensor_pd, ++ &cdsp_root_pd, ++ &mpss_wlan_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *sm8150_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd, ++ &cdsp_root_pd, ++ &mpss_root_pd_gps, ++ &mpss_wlan_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *sm8250_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd, ++ &cdsp_root_pd, ++ &slpi_root_pd, ++ &slpi_sensor_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *sm8350_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd_pdr, ++ &adsp_charger_pd, ++ &cdsp_root_pd, ++ &mpss_root_pd_gps, ++ &slpi_root_pd, ++ &slpi_sensor_pd, ++ NULL, ++}; ++ ++static const struct qcom_pdm_domain_data *sm8550_domains[] = { ++ &adsp_audio_pd, ++ &adsp_root_pd, ++ &adsp_charger_pd, ++ &adsp_sensor_pd, ++ &cdsp_root_pd, ++ &mpss_root_pd_gps, ++ NULL, ++}; ++ ++static const struct of_device_id qcom_pdm_domains[] = { ++ { .compatible = "qcom,apq8064", .data = NULL, }, ++ { .compatible = "qcom,apq8074", .data = NULL, }, ++ { .compatible = "qcom,apq8084", .data = NULL, }, ++ { .compatible = "qcom,apq8096", .data = msm8996_domains, }, ++ { .compatible = "qcom,msm8226", .data = NULL, }, ++ { .compatible = "qcom,msm8974", .data = NULL, }, ++ { .compatible = "qcom,msm8996", .data = msm8996_domains, }, ++ { .compatible = "qcom,msm8998", .data = msm8998_domains, }, ++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, }, ++ { .compatible = "qcom,qcs404", .data = qcs404_domains, }, ++ { .compatible = "qcom,sc7180", .data = sc7180_domains, }, ++ { .compatible = "qcom,sc7280", .data = sc7280_domains, }, ++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, }, ++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, }, ++ { .compatible = "qcom,sda660", .data = sdm660_domains, }, ++ { .compatible = "qcom,sdm660", .data = sdm660_domains, }, ++ { .compatible = "qcom,sdm670", .data = sdm670_domains, }, ++ { .compatible = "qcom,sdm845", .data = sdm845_domains, }, ++ { .compatible = "qcom,sm4250", .data = sm6115_domains, }, ++ { .compatible = "qcom,sm6115", .data = sm6115_domains, }, ++ { .compatible = "qcom,sm6350", .data = sm6350_domains, }, ++ { .compatible = "qcom,sm8150", .data = sm8150_domains, }, ++ { .compatible = "qcom,sm8250", .data = sm8250_domains, }, ++ { .compatible = "qcom,sm8350", .data = sm8350_domains, }, ++ { .compatible = "qcom,sm8450", .data = sm8350_domains, }, ++ { .compatible = "qcom,sm8550", .data = sm8550_domains, }, ++ { .compatible = "qcom,sm8650", .data = sm8550_domains, }, ++ {}, ++}; ++ ++static void qcom_pdm_stop(struct qcom_pdm_data *data) ++{ ++ qcom_pdm_free_domains(data); ++ ++ /* The server is removed automatically */ ++ qmi_handle_release(&data->handle); ++ ++ kfree(data); ++} ++ ++static struct qcom_pdm_data *qcom_pdm_start(void) ++{ ++ const struct qcom_pdm_domain_data * const *domains; ++ const struct of_device_id *match; ++ struct qcom_pdm_data *data; ++ struct device_node *root; ++ int ret, i; ++ ++ root = of_find_node_by_path("/"); ++ if (!root) ++ return ERR_PTR(-ENODEV); ++ ++ match = of_match_node(qcom_pdm_domains, root); ++ of_node_put(root); ++ if (!match) { ++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n"); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ domains = match->data; ++ if (!domains) { ++ pr_debug("PDM: no domains\n"); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ data = kzalloc(sizeof(*data), GFP_KERNEL); ++ if (!data) ++ return ERR_PTR(-ENOMEM); ++ ++ INIT_LIST_HEAD(&data->services); ++ ++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN, ++ NULL, qcom_pdm_msg_handlers); ++ if (ret) { ++ kfree(data); ++ return ERR_PTR(ret); ++ } ++ ++ refcount_set(&data->refcnt, 1); ++ ++ for (i = 0; domains[i]; i++) { ++ ret = qcom_pdm_add_domain(data, domains[i]); ++ if (ret) ++ goto err_stop; ++ } ++ ++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE, ++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE); ++ if (ret) { ++ pr_err("PDM: error adding server %d\n", ret); ++ goto err_stop; ++ } ++ ++ return data; ++ ++err_stop: ++ qcom_pdm_stop(data); ++ ++ return ERR_PTR(ret); ++} ++ ++static int qcom_pdm_probe(struct auxiliary_device *auxdev, ++ const struct auxiliary_device_id *id) ++ ++{ ++ struct qcom_pdm_data *data; ++ int ret = 0; ++ ++ mutex_lock(&qcom_pdm_mutex); ++ ++ if (!__qcom_pdm_data) { ++ data = qcom_pdm_start(); ++ ++ if (IS_ERR(data)) ++ ret = PTR_ERR(data); ++ else ++ __qcom_pdm_data = data; ++ } ++ ++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data); ++ ++ mutex_unlock(&qcom_pdm_mutex); ++ ++ return ret; ++} ++ ++static void qcom_pdm_remove(struct auxiliary_device *auxdev) ++{ ++ struct qcom_pdm_data *data; ++ ++ data = auxiliary_get_drvdata(auxdev); ++ if (!data) ++ return; ++ ++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) { ++ __qcom_pdm_data = NULL; ++ qcom_pdm_stop(data); ++ mutex_unlock(&qcom_pdm_mutex); ++ } ++} ++ ++static const struct auxiliary_device_id qcom_pdm_table[] = { ++ { .name = "qcom_common.pd-mapper" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table); ++ ++static struct auxiliary_driver qcom_pdm_drv = { ++ .name = "qcom-pdm-mapper", ++ .id_table = qcom_pdm_table, ++ .probe = qcom_pdm_probe, ++ .remove = qcom_pdm_remove, ++}; ++module_auxiliary_driver(qcom_pdm_drv); ++ ++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c +index 9b46f42aa146..bf3e4a47165e 100644 +--- a/drivers/soc/qcom/qcom_pdr_msg.c ++++ b/drivers/soc/qcom/qcom_pdr_msg.c +@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = { + }; + EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei); + ++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = { ++ { ++ .data_type = QMI_STRING, ++ .elem_len = SERVREG_NAME_LENGTH + 1, ++ .elem_size = sizeof(char), ++ .array_type = VAR_LEN_ARRAY, ++ .tlv_type = 0x01, ++ .offset = offsetof(struct servreg_loc_pfr_req, service) ++ }, ++ { ++ .data_type = QMI_STRING, ++ .elem_len = SERVREG_NAME_LENGTH + 1, ++ .elem_size = sizeof(char), ++ .array_type = VAR_LEN_ARRAY, ++ .tlv_type = 0x02, ++ .offset = offsetof(struct servreg_loc_pfr_req, reason) ++ }, ++ {} ++}; ++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei); ++ ++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = { ++ { ++ .data_type = QMI_STRUCT, ++ .elem_len = 1, ++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp), ++ .tlv_type = 0x02, ++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp), ++ .ei_array = qmi_response_type_v01_ei, ++ }, ++ {} ++}; ++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei); ++ + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Qualcomm Protection Domain messages data"); + +From: Dmitry Baryshkov +Date: Sun, 12 May 2024 00:56:07 +0300 +Subject: [PATCH v8 5/5] remoteproc: qcom: enable in-kernel PD mapper + +Request in-kernel protection domain mapper to be started before starting +Qualcomm DSP and release it once DSP is stopped. Once all DSPs are +stopped, the PD mapper will be stopped too. + +Signed-off-by: Dmitry Baryshkov +--- + drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++ + drivers/remoteproc/qcom_common.h | 10 +++++ + drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++ + drivers/remoteproc/qcom_q6v5_mss.c | 3 ++ + drivers/remoteproc/qcom_q6v5_pas.c | 3 ++ + drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++ + 6 files changed, 109 insertions(+) + +diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c +index 03e5f5d533eb..8c8688f99f0a 100644 +--- a/drivers/remoteproc/qcom_common.c ++++ b/drivers/remoteproc/qcom_common.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -25,6 +26,7 @@ + #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev) + #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev) + #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev) ++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev) + + #define MAX_NUM_OF_SS 10 + #define MAX_REGION_NAME_LENGTH 16 +@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr) + } + EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev); + ++static void pdm_dev_release(struct device *dev) ++{ ++ struct auxiliary_device *adev = to_auxiliary_dev(dev); ++ ++ kfree(adev); ++} ++ ++static int pdm_notify_prepare(struct rproc_subdev *subdev) ++{ ++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev); ++ struct auxiliary_device *adev; ++ int ret; ++ ++ adev = kzalloc(sizeof(*adev), GFP_KERNEL); ++ if (!adev) ++ return -ENOMEM; ++ ++ adev->dev.parent = pdm->dev; ++ adev->dev.release = pdm_dev_release; ++ adev->name = "pd-mapper"; ++ adev->id = pdm->index; ++ ++ ret = auxiliary_device_init(adev); ++ if (ret) { ++ kfree(adev); ++ return ret; ++ } ++ ++ ret = auxiliary_device_add(adev); ++ if (ret) { ++ auxiliary_device_uninit(adev); ++ return ret; ++ } ++ ++ pdm->adev = adev; ++ ++ return 0; ++} ++ ++ ++static void pdm_notify_unprepare(struct rproc_subdev *subdev) ++{ ++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev); ++ ++ if (!pdm->adev) ++ return; ++ ++ auxiliary_device_delete(pdm->adev); ++ auxiliary_device_uninit(pdm->adev); ++ pdm->adev = NULL; ++} ++ ++/** ++ * qcom_add_pdm_subdev() - register PD Mapper subdevice ++ * @rproc: rproc handle ++ * @pdm: PDM subdevice handle ++ * ++ * Register @pdm so that Protection Device mapper service is started when the ++ * DSP is started too. ++ */ ++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm) ++{ ++ pdm->dev = &rproc->dev; ++ pdm->index = rproc->index; ++ ++ pdm->subdev.prepare = pdm_notify_prepare; ++ pdm->subdev.unprepare = pdm_notify_unprepare; ++ ++ rproc_add_subdev(rproc, &pdm->subdev); ++} ++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev); ++ ++/** ++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice ++ * @rproc: rproc handle ++ * @pdm: PDM subdevice handle ++ * ++ * Remove the PD Mapper subdevice. ++ */ ++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm) ++{ ++ rproc_remove_subdev(rproc, &pdm->subdev); ++} ++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev); ++ + MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver"); + MODULE_LICENSE("GPL v2"); +diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h +index 9ef4449052a9..b07fbaa091a0 100644 +--- a/drivers/remoteproc/qcom_common.h ++++ b/drivers/remoteproc/qcom_common.h +@@ -34,6 +34,13 @@ struct qcom_rproc_ssr { + struct qcom_ssr_subsystem *info; + }; + ++struct qcom_rproc_pdm { ++ struct rproc_subdev subdev; ++ struct device *dev; ++ int index; ++ struct auxiliary_device *adev; ++}; ++ + void qcom_minidump(struct rproc *rproc, unsigned int minidump_id, + void (*rproc_dumpfn_t)(struct rproc *rproc, + struct rproc_dump_segment *segment, void *dest, size_t offset, +@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr, + const char *ssr_name); + void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr); + ++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm); ++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm); ++ + #if IS_ENABLED(CONFIG_QCOM_SYSMON) + struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc, + const char *name, +diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c +index 1d24c9b656a8..572dcb0f055b 100644 +--- a/drivers/remoteproc/qcom_q6v5_adsp.c ++++ b/drivers/remoteproc/qcom_q6v5_adsp.c +@@ -112,6 +112,7 @@ struct qcom_adsp { + struct dev_pm_domain_list *pd_list; + + struct qcom_rproc_glink glink_subdev; ++ struct qcom_rproc_pdm pdm_subdev; + struct qcom_rproc_ssr ssr_subdev; + struct qcom_sysmon *sysmon; + +@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev) + goto disable_pm; + + qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name); ++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev); + qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name); + adsp->sysmon = qcom_add_sysmon_subdev(rproc, + desc->sysmon_name, +@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev) + + qcom_q6v5_deinit(&adsp->q6v5); + qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev); ++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev); + qcom_remove_sysmon_subdev(adsp->sysmon); + qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); + qcom_rproc_pds_detach(adsp); +diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c +index 1779fc890e10..2a42215ce8e0 100644 +--- a/drivers/remoteproc/qcom_q6v5_mss.c ++++ b/drivers/remoteproc/qcom_q6v5_mss.c +@@ -228,6 +228,7 @@ struct q6v5 { + + struct qcom_rproc_glink glink_subdev; + struct qcom_rproc_subdev smd_subdev; ++ struct qcom_rproc_pdm pdm_subdev; + struct qcom_rproc_ssr ssr_subdev; + struct qcom_sysmon *sysmon; + struct platform_device *bam_dmux; +@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev) + qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS); + qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss"); + qcom_add_smd_subdev(rproc, &qproc->smd_subdev); ++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev); + qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss"); + qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12); + if (IS_ERR(qproc->sysmon)) { +@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev) + qcom_q6v5_deinit(&qproc->q6v5); + qcom_remove_sysmon_subdev(qproc->sysmon); + qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev); ++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev); + qcom_remove_smd_subdev(rproc, &qproc->smd_subdev); + qcom_remove_glink_subdev(rproc, &qproc->glink_subdev); + +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 54d8005d40a3..399c3bc104bd 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -109,6 +109,7 @@ struct qcom_adsp { + + struct qcom_rproc_glink glink_subdev; + struct qcom_rproc_subdev smd_subdev; ++ struct qcom_rproc_pdm pdm_subdev; + struct qcom_rproc_ssr ssr_subdev; + struct qcom_sysmon *sysmon; + +@@ -771,6 +772,7 @@ static int adsp_probe(struct platform_device *pdev) + + qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name); + qcom_add_smd_subdev(rproc, &adsp->smd_subdev); ++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev); + adsp->sysmon = qcom_add_sysmon_subdev(rproc, + desc->sysmon_name, + desc->ssctl_id); +@@ -805,6 +807,7 @@ static void adsp_remove(struct platform_device *pdev) + qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev); + qcom_remove_sysmon_subdev(adsp->sysmon); + qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev); ++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev); + qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); + adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count); + device_init_wakeup(adsp->dev, false); +diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c +index 94f68c919ee6..e913dabae992 100644 +--- a/drivers/remoteproc/qcom_q6v5_wcss.c ++++ b/drivers/remoteproc/qcom_q6v5_wcss.c +@@ -148,6 +148,7 @@ struct q6v5_wcss { + bool requires_force_stop; + + struct qcom_rproc_glink glink_subdev; ++ struct qcom_rproc_pdm pdm_subdev; + struct qcom_rproc_ssr ssr_subdev; + }; + +@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev) + return ret; + + qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss"); ++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev); + qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss"); + + if (desc->ssctl_id) +@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev) + struct q6v5_wcss *wcss = rproc->priv; + + qcom_q6v5_deinit(&wcss->q6v5); ++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev); + rproc_del(rproc); + } + diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template index 0db68f04bb6e23..f9ff81b3d68d62 100644 --- a/srcpkgs/linux6.8/template +++ b/srcpkgs/linux6.8/template @@ -1,7 +1,7 @@ # Template file for 'linux6.8' pkgname=linux6.8 version=6.8.12 -revision=1 +revision=2 short_desc="Linux kernel and modules (${version%.*} series)" maintainer="Duncaen " license="GPL-2.0-only"