From 326031a95d2a8a34863fa6b07feef3327b314116 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.2 --- srcpkgs/x13s-base/INSTALL | 16 ++++++++++++++++ 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 | 18 ++++++++++++++++++ 6 files changed, 52 insertions(+) create mode 100644 srcpkgs/x13s-base/INSTALL 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/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..347e58d4c38dd8 --- /dev/null +++ b/srcpkgs/x13s-base/template @@ -0,0 +1,18 @@ +# Template file for 'x13s-base' +pkgname=x13s-base +version=0.3 +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}"/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 cb1d870b7206a444e058c9cf3c9e55a5c47f130b 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 | 2011 +++++++++++++++++ srcpkgs/linux6.8/template | 2 +- 3 files changed, 2070 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 ada0e5a9e51201..97e9d729c3aa38 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..a0288d36034b11 --- /dev/null +++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch @@ -0,0 +1,2011 @@ +source: https://patchwork.kernel.org/project/linux-remoteproc/cover/20240424-qcom-pd-mapper-v7-0-05f7fc646e0f@linaro.org/ + +From: Dmitry Baryshkov +Date: Wed, 24 Apr 2024 12:27:57 +0300 +Subject: [PATCH v7 1/6] 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 +Signed-off-by: Dmitry Baryshkov +--- + drivers/soc/qcom/pdr_interface.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c +index a1b6a4081dea..19cfe4b41235 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 = { + +From: Dmitry Baryshkov +Date: Wed, 24 Apr 2024 12:27:58 +0300 +Subject: [PATCH v7 2/6] 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") +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 19cfe4b41235..3c6f2d21e5e4 100644 +--- a/drivers/soc/qcom/pdr_interface.c ++++ b/drivers/soc/qcom/pdr_interface.c +@@ -415,7 +415,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: Wed, 24 Apr 2024 12:27:59 +0300 +Subject: [PATCH v7 3/6] 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 +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: Wed, 24 Apr 2024 12:28:00 +0300 +Subject: [PATCH v7 4/6] soc: qcom: qmi: add a way to remove running service + +Add qmi_del_server(), a pair to qmi_add_server(), a way to remove +running server from the QMI socket. This is e.g. necessary for +pd-mapper, which needs to readd a server each time the DSP is started or +stopped. + +Tested-by: Neil Armstrong # on SM8550-QRD +Signed-off-by: Dmitry Baryshkov +--- + drivers/soc/qcom/qmi_interface.c | 67 ++++++++++++++++++++++++++++++++++++++++ + include/linux/soc/qcom/qmi.h | 2 ++ + 2 files changed, 69 insertions(+) + +diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c +index bb98b06e87f8..18ff2015c682 100644 +--- a/drivers/soc/qcom/qmi_interface.c ++++ b/drivers/soc/qcom/qmi_interface.c +@@ -289,6 +289,73 @@ int qmi_add_server(struct qmi_handle *qmi, unsigned int service, + } + EXPORT_SYMBOL_GPL(qmi_add_server); + ++static void qmi_send_del_server(struct qmi_handle *qmi, struct qmi_service *svc) ++{ ++ struct qrtr_ctrl_pkt pkt; ++ struct sockaddr_qrtr sq; ++ struct msghdr msg = { }; ++ struct kvec iv = { &pkt, sizeof(pkt) }; ++ int ret; ++ ++ memset(&pkt, 0, sizeof(pkt)); ++ pkt.cmd = cpu_to_le32(QRTR_TYPE_DEL_SERVER); ++ pkt.server.service = cpu_to_le32(svc->service); ++ pkt.server.instance = cpu_to_le32(svc->version | svc->instance << 8); ++ pkt.server.node = cpu_to_le32(qmi->sq.sq_node); ++ pkt.server.port = cpu_to_le32(qmi->sq.sq_port); ++ ++ sq.sq_family = qmi->sq.sq_family; ++ sq.sq_node = qmi->sq.sq_node; ++ sq.sq_port = QRTR_PORT_CTRL; ++ ++ msg.msg_name = &sq; ++ msg.msg_namelen = sizeof(sq); ++ ++ mutex_lock(&qmi->sock_lock); ++ if (qmi->sock) { ++ ret = kernel_sendmsg(qmi->sock, &msg, &iv, 1, sizeof(pkt)); ++ if (ret < 0) ++ pr_err("send service deregistration failed: %d\n", ret); ++ } ++ mutex_unlock(&qmi->sock_lock); ++} ++ ++/** ++ * qmi_del_server() - register a service with the name service ++ * @qmi: qmi handle ++ * @service: type of the service ++ * @instance: instance of the service ++ * @version: version of the service ++ * ++ * Remove registration of the service with the name service. This notifies ++ * clients that they should no longer send messages to the client associated ++ * with @qmi. ++ * ++ * Return: 0 on success, negative errno on failure. ++ */ ++int qmi_del_server(struct qmi_handle *qmi, unsigned int service, ++ unsigned int version, unsigned int instance) ++{ ++ struct qmi_service *svc; ++ struct qmi_service *tmp; ++ ++ list_for_each_entry_safe(svc, tmp, &qmi->services, list_node) { ++ if (svc->service != service || ++ svc->version != version || ++ svc->instance != instance) ++ continue; ++ ++ qmi_send_del_server(qmi, svc); ++ list_del(&svc->list_node); ++ kfree(svc); ++ ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++EXPORT_SYMBOL_GPL(qmi_del_server); ++ + /** + * qmi_txn_init() - allocate transaction id within the given QMI handle + * @qmi: QMI handle +diff --git a/include/linux/soc/qcom/qmi.h b/include/linux/soc/qcom/qmi.h +index 469e02d2aa0d..5039c30e4bdc 100644 +--- a/include/linux/soc/qcom/qmi.h ++++ b/include/linux/soc/qcom/qmi.h +@@ -241,6 +241,8 @@ int qmi_add_lookup(struct qmi_handle *qmi, unsigned int service, + unsigned int version, unsigned int instance); + int qmi_add_server(struct qmi_handle *qmi, unsigned int service, + unsigned int version, unsigned int instance); ++int qmi_del_server(struct qmi_handle *qmi, unsigned int service, ++ unsigned int version, unsigned int instance); + + int qmi_handle_init(struct qmi_handle *qmi, size_t max_msg_len, + const struct qmi_ops *ops, + +From: Dmitry Baryshkov +Date: Wed, 24 Apr 2024 12:28:01 +0300 +Subject: [PATCH v7 5/6] 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. + +Signed-off-by: Dmitry Baryshkov +--- + drivers/soc/qcom/Kconfig | 10 + + drivers/soc/qcom/Makefile | 1 + + drivers/soc/qcom/pdr_internal.h | 14 + + drivers/soc/qcom/qcom_pd_mapper.c | 656 +++++++++++++++++++++++++++++++++++++ + drivers/soc/qcom/qcom_pdr_msg.c | 34 ++ + include/linux/soc/qcom/pd_mapper.h | 28 ++ + 6 files changed, 743 insertions(+) + +diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig +index 95973c6b828f..f666366841b8 100644 +--- a/drivers/soc/qcom/Kconfig ++++ b/drivers/soc/qcom/Kconfig +@@ -72,6 +72,16 @@ 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 ++ 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..ba5440506c95 +--- /dev/null ++++ b/drivers/soc/qcom/qcom_pd_mapper.c +@@ -0,0 +1,656 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Qualcomm Protection Domain mapper ++ * ++ * Copyright (c) 2023 Linaro Ltd. ++ */ ++ ++#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; ++}; ++ ++static DEFINE_MUTEX(qcom_pdm_count_mutex); /* guards count */ ++/* ++ * It is not possible to use refcount_t here. The service needs to go to 0 and ++ * back without warnings. ++ */ ++static unsigned int qcom_pdm_count; ++ ++static DEFINE_MUTEX(qcom_pdm_mutex); ++static struct qmi_handle qcom_pdm_handle; ++static LIST_HEAD(qcom_pdm_services); ++ ++static struct qcom_pdm_service *qcom_pdm_find(const char *name) ++{ ++ struct qcom_pdm_service *service; ++ ++ list_for_each_entry(service, &qcom_pdm_services, list) { ++ if (!strcmp(service->name, name)) ++ return service; ++ } ++ ++ return NULL; ++} ++ ++static int qcom_pdm_add_service_domain(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(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, &qcom_pdm_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(const struct qcom_pdm_domain_data *data) ++{ ++ int ret; ++ int i; ++ ++ ret = qcom_pdm_add_service_domain(TMS_SERVREG_SERVICE, ++ data->domain, ++ data->instance_id); ++ if (ret) ++ return ret; ++ ++ for (i = 0; data->services[i]; i++) { ++ ret = qcom_pdm_add_service_domain(data->services[i], ++ data->domain, ++ data->instance_id); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++ ++} ++ ++static void qcom_pdm_free_domains(void) ++{ ++ struct qcom_pdm_service *service, *tservice; ++ struct qcom_pdm_domain *domain, *tdomain; ++ ++ list_for_each_entry_safe(service, tservice, &qcom_pdm_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) ++{ ++ const struct servreg_get_domain_list_req *req = decoded; ++ struct servreg_get_domain_list_resp *rsp = kzalloc(sizeof(*rsp), GFP_KERNEL); ++ struct qcom_pdm_service *service; ++ u32 offset; ++ int ret; ++ ++ 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(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, ++ &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,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 int qcom_pdm_start(void) ++{ ++ const struct of_device_id *match; ++ const struct qcom_pdm_domain_data * const *domains; ++ struct device_node *root; ++ int ret, i; ++ ++ root = of_find_node_by_path("/"); ++ if (!root) ++ return -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 -ENODEV; ++ } ++ ++ domains = match->data; ++ if (!domains) { ++ pr_debug("PDM: no domains\n"); ++ return -ENODEV; ++ } ++ ++ mutex_lock(&qcom_pdm_mutex); ++ for (i = 0; domains[i]; i++) { ++ ret = qcom_pdm_add_domain(domains[i]); ++ if (ret) ++ goto free_domains; ++ } ++ ++ ret = qmi_handle_init(&qcom_pdm_handle, 1024, ++ NULL, qcom_pdm_msg_handlers); ++ if (ret) ++ goto free_domains; ++ ++ ret = qmi_add_server(&qcom_pdm_handle, SERVREG_LOCATOR_SERVICE, ++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE); ++ if (ret) { ++ pr_err("PDM: error adding server %d\n", ret); ++ goto release_handle; ++ } ++ mutex_unlock(&qcom_pdm_mutex); ++ ++ return 0; ++ ++release_handle: ++ qmi_handle_release(&qcom_pdm_handle); ++ ++free_domains: ++ qcom_pdm_free_domains(); ++ mutex_unlock(&qcom_pdm_mutex); ++ ++ return ret; ++} ++ ++static void qcom_pdm_stop(void) ++{ ++ qmi_del_server(&qcom_pdm_handle, SERVREG_LOCATOR_SERVICE, ++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE); ++ ++ qmi_handle_release(&qcom_pdm_handle); ++ ++ qcom_pdm_free_domains(); ++} ++ ++/** ++ * qcom_pdm_get() - ensure that PD mapper is up and running ++ * ++ * Start the in-kernel Qualcomm DSP protection domain mapper service if it was ++ * not running. ++ * ++ * Return: 0 on success, negative error code on failure. ++ */ ++int qcom_pdm_get(void) ++{ ++ int ret = 0; ++ ++ mutex_lock(&qcom_pdm_count_mutex); ++ ++ if (!qcom_pdm_count) ++ ret = qcom_pdm_start(); ++ if (!ret) ++ ++qcom_pdm_count; ++ ++ mutex_unlock(&qcom_pdm_count_mutex); ++ ++ /* ++ * If it is -ENODEV, the plaform is not supported by the in-kernel ++ * mapper. Still return 0 to rproc driver, userspace daemon will be ++ * used instead of the kernel server. ++ */ ++ if (ret == -ENODEV) ++ return 0; ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(qcom_pdm_get); ++ ++/** ++ * qcom_pdm_release() - possibly stop PD mapper service ++ * ++ * Decreases refcount, stopping the server when the last user was removed. ++ */ ++void qcom_pdm_release(void) ++{ ++ mutex_lock(&qcom_pdm_count_mutex); ++ ++ if (qcom_pdm_count == 1) ++ qcom_pdm_stop(); ++ ++ if (qcom_pdm_count >= 1) ++ --qcom_pdm_count; ++ ++ mutex_unlock(&qcom_pdm_count_mutex); ++} ++EXPORT_SYMBOL_GPL(qcom_pdm_release); ++ ++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"); +diff --git a/include/linux/soc/qcom/pd_mapper.h b/include/linux/soc/qcom/pd_mapper.h +new file mode 100644 +index 000000000000..d0dd3dfc8fea +--- /dev/null ++++ b/include/linux/soc/qcom/pd_mapper.h +@@ -0,0 +1,28 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Qualcomm Protection Domain mapper ++ * ++ * Copyright (c) 2023 Linaro Ltd. ++ */ ++#ifndef __QCOM_PD_MAPPER__ ++#define __QCOM_PD_MAPPER__ ++ ++#if IS_ENABLED(CONFIG_QCOM_PD_MAPPER) ++ ++int qcom_pdm_get(void); ++void qcom_pdm_release(void); ++ ++#else ++ ++static inline int qcom_pdm_get(void) ++{ ++ return 0; ++} ++ ++static inline void qcom_pdm_release(void) ++{ ++} ++ ++#endif ++ ++#endif + +From: Dmitry Baryshkov +Date: Wed, 24 Apr 2024 12:28:02 +0300 +Subject: [PATCH v7 6/6] 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/Kconfig | 4 ++++ + drivers/remoteproc/qcom_q6v5_adsp.c | 11 ++++++++++- + drivers/remoteproc/qcom_q6v5_mss.c | 10 +++++++++- + drivers/remoteproc/qcom_q6v5_pas.c | 12 +++++++++++- + drivers/remoteproc/qcom_q6v5_wcss.c | 12 +++++++++++- + 5 files changed, 45 insertions(+), 4 deletions(-) + +diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig +index 48845dc8fa85..a0ce552f89a1 100644 +--- a/drivers/remoteproc/Kconfig ++++ b/drivers/remoteproc/Kconfig +@@ -181,6 +181,7 @@ config QCOM_Q6V5_ADSP + depends on QCOM_SYSMON || QCOM_SYSMON=n + depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n + depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n ++ depends on QCOM_PD_MAPPER || QCOM_PD_MAPPER=n + select MFD_SYSCON + select QCOM_PIL_INFO + select QCOM_MDT_LOADER +@@ -201,6 +202,7 @@ config QCOM_Q6V5_MSS + depends on QCOM_SYSMON || QCOM_SYSMON=n + depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n + depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n ++ depends on QCOM_PD_MAPPER || QCOM_PD_MAPPER=n + select MFD_SYSCON + select QCOM_MDT_LOADER + select QCOM_PIL_INFO +@@ -221,6 +223,7 @@ config QCOM_Q6V5_PAS + depends on QCOM_SYSMON || QCOM_SYSMON=n + depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n + depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n ++ depends on QCOM_PD_MAPPER || QCOM_PD_MAPPER=n + select MFD_SYSCON + select QCOM_PIL_INFO + select QCOM_MDT_LOADER +@@ -243,6 +246,7 @@ config QCOM_Q6V5_WCSS + depends on QCOM_SYSMON || QCOM_SYSMON=n + depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n + depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n ++ depends on QCOM_PD_MAPPER || QCOM_PD_MAPPER=n + select MFD_SYSCON + select QCOM_MDT_LOADER + select QCOM_PIL_INFO +diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c +index 1d24c9b656a8..02d0c626b03b 100644 +--- a/drivers/remoteproc/qcom_q6v5_adsp.c ++++ b/drivers/remoteproc/qcom_q6v5_adsp.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -375,10 +376,14 @@ static int adsp_start(struct rproc *rproc) + int ret; + unsigned int val; + +- ret = qcom_q6v5_prepare(&adsp->q6v5); ++ ret = qcom_pdm_get(); + if (ret) + return ret; + ++ ret = qcom_q6v5_prepare(&adsp->q6v5); ++ if (ret) ++ goto put_pdm; ++ + ret = adsp_map_carveout(rproc); + if (ret) { + dev_err(adsp->dev, "ADSP smmu mapping failed\n"); +@@ -446,6 +451,8 @@ static int adsp_start(struct rproc *rproc) + adsp_unmap_carveout(rproc); + disable_irqs: + qcom_q6v5_unprepare(&adsp->q6v5); ++put_pdm: ++ qcom_pdm_release(); + + return ret; + } +@@ -478,6 +485,8 @@ static int adsp_stop(struct rproc *rproc) + if (handover) + qcom_adsp_pil_handover(&adsp->q6v5); + ++ qcom_pdm_release(); ++ + return ret; + } + +diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c +index 1779fc890e10..791f11e7adbf 100644 +--- a/drivers/remoteproc/qcom_q6v5_mss.c ++++ b/drivers/remoteproc/qcom_q6v5_mss.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -1581,10 +1582,14 @@ static int q6v5_start(struct rproc *rproc) + int xfermemop_ret; + int ret; + +- ret = q6v5_mba_load(qproc); ++ ret = qcom_pdm_get(); + if (ret) + return ret; + ++ ret = q6v5_mba_load(qproc); ++ if (ret) ++ goto put_pdm; ++ + dev_info(qproc->dev, "MBA booted with%s debug policy, loading mpss\n", + qproc->dp_size ? "" : "out"); + +@@ -1613,6 +1618,8 @@ static int q6v5_start(struct rproc *rproc) + reclaim_mpss: + q6v5_mba_reclaim(qproc); + q6v5_dump_mba_logs(qproc); ++put_pdm: ++ qcom_pdm_release(); + + return ret; + } +@@ -1627,6 +1634,7 @@ static int q6v5_stop(struct rproc *rproc) + dev_err(qproc->dev, "timed out on wait\n"); + + q6v5_mba_reclaim(qproc); ++ qcom_pdm_release(); + + return 0; + } +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 54d8005d40a3..653e54f975fc 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -261,10 +262,14 @@ static int adsp_start(struct rproc *rproc) + struct qcom_adsp *adsp = rproc->priv; + int ret; + +- ret = qcom_q6v5_prepare(&adsp->q6v5); ++ ret = qcom_pdm_get(); + if (ret) + return ret; + ++ ret = qcom_q6v5_prepare(&adsp->q6v5); ++ if (ret) ++ goto put_pdm; ++ + ret = adsp_pds_enable(adsp, adsp->proxy_pds, adsp->proxy_pd_count); + if (ret < 0) + goto disable_irqs; +@@ -356,6 +361,9 @@ static int adsp_start(struct rproc *rproc) + /* Remove pointer to the loaded firmware, only valid in adsp_load() & adsp_start() */ + adsp->firmware = NULL; + ++put_pdm: ++ qcom_pdm_release(); ++ + return ret; + } + +@@ -399,6 +407,8 @@ static int adsp_stop(struct rproc *rproc) + if (handover) + qcom_pas_handover(&adsp->q6v5); + ++ qcom_pdm_release(); ++ + return ret; + } + +diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c +index 94f68c919ee6..6ed60f3f3eee 100644 +--- a/drivers/remoteproc/qcom_q6v5_wcss.c ++++ b/drivers/remoteproc/qcom_q6v5_wcss.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include "qcom_common.h" + #include "qcom_pil_info.h" + #include "qcom_q6v5.h" +@@ -240,13 +241,17 @@ static int q6v5_wcss_start(struct rproc *rproc) + struct q6v5_wcss *wcss = rproc->priv; + int ret; + ++ ret = qcom_pdm_get(); ++ if (ret) ++ return ret; ++ + qcom_q6v5_prepare(&wcss->q6v5); + + /* Release Q6 and WCSS reset */ + ret = reset_control_deassert(wcss->wcss_reset); + if (ret) { + dev_err(wcss->dev, "wcss_reset failed\n"); +- return ret; ++ goto put_pdm; + } + + ret = reset_control_deassert(wcss->wcss_q6_reset); +@@ -288,6 +293,9 @@ static int q6v5_wcss_start(struct rproc *rproc) + wcss_reset: + reset_control_assert(wcss->wcss_reset); + ++put_pdm: ++ qcom_pdm_release(); ++ + return ret; + } + +@@ -735,6 +743,8 @@ static int q6v5_wcss_stop(struct rproc *rproc) + + qcom_q6v5_unprepare(&wcss->q6v5); + ++ qcom_pdm_release(); ++ + return 0; + } + diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template index 6c1328da295d7c..7ee5d17b608095 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.9 -revision=1 +revision=2 short_desc="Linux kernel and modules (${version%.*} series)" maintainer="Duncaen " license="GPL-2.0-only"