diff --git a/.gitignore b/.gitignore index 38df5eb..066083f 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ libtool stamp-h1 .deps/ +.dirstamp .libs/ # Compiled objects @@ -31,10 +32,14 @@ stamp-h1 *.lo *.la +# Generated service units +files/*.service + # Compiled programs src/adsprpcd src/cdsprpcd src/sdsprpcd +src/gdsprpcd test/fastrpc_test # make dist tarballs diff --git a/Docs/images/Term_definitions.png b/Docs/images/Term_definitions.png deleted file mode 100644 index 9875fdb..0000000 Binary files a/Docs/images/Term_definitions.png and /dev/null differ diff --git a/Makefile.am b/Makefile.am index f068b7c..111c639 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS = inc src test +SUBDIRS = inc src test files ACLOCAL_AMFLAGS = -I m4 diff --git a/README.md b/README.md index 55888c7..e5857a4 100644 --- a/README.md +++ b/README.md @@ -12,19 +12,108 @@ FastRPC interfaces are defined in an IDL file, and they are compiled using the Q The following diagram depicts the major FastRPC software components on the CPU and DSP. -![FastRPC Architecture](Docs/images/FastRPC_architecture.png) +```mermaid +flowchart TB +subgraph SMD["FastRPC Architecture"] +direction TB + +subgraph TOP[" "] +direction LR + +subgraph CPU["CPU"] +direction TB +subgraph Application["Application"] +direction TB +Stub["Stub"] +FRPC_UD["FastRPC
user
driver"] +end +FRPC_KD["FastRPC Kernel
driver"] +end + +subgraph DSP["DSP"] +direction TB +subgraph User_PD["User PD"] +direction TB +Skel["Skel"] +FRPC_DD["FastRPC
DSP user
driver"] +end +FRPC_DSP_KD["FastRPC DSP
driver"] +end + +end +end + +classDef generated fill:#E6E6FA,stroke:#9370DB,color:#000 +classDef fastrpc fill:#4169E1,stroke:#000,color:#000 +classDef shared fill:#FAFAFA,stroke:#666,color:#000 +classDef userpdbox fill:#ABDBE3,stroke:#666,color:#000 +classDef mainbox fill:#7FB3CD,stroke:#666,color:#000 +classDef topbox fill:none,stroke:none,color:none + +class Stub,Skel generated +class FRPC_UD,FRPC_KD,FRPC_DD,FRPC_DSP_KD fastrpc +class SMD shared +class Application,User_PD userpdbox +class CPU,DSP mainbox +class TOP topbox + +Stub <--> FRPC_UD +FRPC_UD <--> FRPC_KD +FRPC_KD <--> |rpmsg| FRPC_DSP_KD +FRPC_DSP_KD <--> FRPC_DD +FRPC_DD <--> Skel + +linkStyle default stroke:#000 +``` -**Stub and skel** are generated by the IDL compiler. Other modules are part of the software stack on the device. +**Stub** and **Skel** are generated by the IDL compiler. The modules shown in blue blocks in the diagram are part of the FastRPC software stack on the device. **Definition of the terms in the diagram:** -![Term Definitions](Docs/images/Term_definitions.png) - +| Term | Description | +|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------| +| Application | User mode process that initiates the remote invocation | +| Stub | Auto-generated code that takes care of marshaling parameters and runs on the CPU | +| FastRPC user driver on CPU | User mode library that is used by the stub code to do remote invocations | +| FastRPC Kernel Driver | Receives the remote invocations from the client, queues them up for transport to the DSP side over rpmsg, and then waits for the response after signaling the remote side | +| rpmsg | Remote Processor Messaging is the transport mechanism used between the CPU-side FastRPC kernel driver and the DSP-side FastRPC driver to exchange FastRPC requests and responses | +| FastRPC DSP Driver | Dequeues the messages received over rpmsg from the FastRPC kernel driver and dispatches them for processing | +| FastRPC user driver on DSP | User mode code that includes a shell executable to run in the user protection domain (PD) on the DSP and complete the remote invocations to the skel library | +| Skel | Auto-generated code that un-marshals parameters and invokes the user-defined implementation of the function that runs on the DSP | +| User PD | User protection domain on the DSP that provides the environment to run the user code | + ### FastRPC Workflow The FastRPC framework consists of the following components. -![FastRPC Workflow](Docs/images/FastRPC_workflow.png) +```mermaid +flowchart LR +subgraph CPU +UC[User Code] +Stub[Stub] +FF[FastRPC Framework] +end +subgraph DSP +FD[FastRPC DSP Framework] +Skel[Skel] +MI[Method Implementation] +end +UC --> |" 1 "| Stub +Stub --> |" 10 "| UC +Stub --> |" 2 "| FF +FF --> |" 9 "| Stub +FF --> |" 3 "| FD +FD --> |" 8 "| FF +FD --> |" 4 "| Skel +Skel --> |" 7 "| FD +Skel --> |" 5 "| MI +MI --> |" 6 "| Skel +classDef generated fill:#E6E6FA,stroke:#9370DB,color:#2A0066 +classDef fastrpc fill:#4169E1,stroke:#000,color:#FFFFFF +classDef shared fill:#F5F5F5,stroke:#666 +class UC,Stub,Skel,MI generated +class FF,FD fastrpc +``` **Workflow:** @@ -46,6 +135,35 @@ Hexagon SDK documentation covers all the required details about FastRPC. Please ## Build & Installation +### Setting up the fastrpc group + +The udev rules set `/dev/fastrpc-*dsp` device nodes to `root:fastrpc` with `0640` permissions and +grant the `fastrpc` group read/write access to `/dev/dma_heap/system` (required for memory allocation). +Applications that use `libfastrpc` must therefore belong to the `fastrpc` group. + +The build system installs a `sysusers.d` configuration file that automatically creates the `fastrpc` group when `systemd-sysusers` runs (typically at boot or via package manager triggers). + +To manually create the group: + +```bash +groupadd --system fastrpc +``` + +Or trigger systemd-sysusers: + +```bash +sudo systemd-sysusers +``` + +To grant an application user access to FastRPC devices: + +```bash +usermod -aG fastrpc +``` + +The services are automatically started by udev when FastRPC devices are detected. +No manual `systemctl enable` is required. + ### Steps to Generate Native Binaries on Device ```bash @@ -53,16 +171,50 @@ git clone https://github.com/quic/fastrpc cd fastrpc ./gitcompile sudo make install +sudo ldconfig # Update dynamic linker cache +sudo systemd-sysusers # Create fastrpc group ``` -### Steps to Generate ARM Binaries Using Linaro Toolchain on Ubuntu Build Machine +### Steps to cross-compile the project on Ubuntu + +1. **Install the cross compiler and required dependencies:** + + Install cross-compilation toolchain: + ```bash + sudo apt install g++-aarch64-linux-gnu binutils-aarch64-linux-gnu + ``` -1. **Install Linaro tools and add the tools bin location to the path:** + Install and build libyaml: + ```bash + git clone https://github.com/yaml/libyaml.git + cd libyaml + ./bootstrap + ./configure --host=aarch64-linux-gnu + make + sudo make install + cd .. + ``` + + Install and build libmd: + ```bash + git clone https://git.hadrons.org/git/libmd.git + cd libmd + ./autogen + ./configure --host=aarch64-linux-gnu + make + sudo make install + cd .. + ``` + Install and build libbsd: ```bash - wget -c https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.5.0-2019.12-i686_aarch64-linux-gnu.tar.xz - tar xf gcc-linaro-7.5.0-2019.12-i686_aarch64-linux-gnu.tar.xz - export PATH="$PATH:/toolchain/bin" + git clone https://gitlab.freedesktop.org/libbsd/libbsd.git + cd libbsd + ./autogen + ./configure --host=aarch64-linux-gnu + make + sudo make install + cd .. ``` 2. **Create softlink files for the compiler, linker, and other tools. Create environment variables as below for the auto tools:** @@ -196,4 +348,4 @@ Thanks for your interest in contributing to FastRPC! Please read our [Contributi ## License -FastRPC is licensed under the BSD 3-clause "New" or "Revised" License. Check out the [LICENSE](LICENSE.txt) for more details. \ No newline at end of file +FastRPC is licensed under the BSD 3-clause "New" or "Revised" License. Check out the [LICENSE](LICENSE.txt) for more details. diff --git a/ci/MACHINES.json b/ci/MACHINES.json index 44d8ecd..df35c5a 100644 --- a/ci/MACHINES.json +++ b/ci/MACHINES.json @@ -16,5 +16,11 @@ "linuxFirmware": "qcs8300", "lavaDeviceName": "qcs8300-ride", "hexDSPBinary": "qcs8300" + }, + "qcs615-ride": { + "deviceTree": "qcs615-ride", + "linuxFirmware": "qcs615", + "lavaDeviceName": "qcs615-ride", + "hexDSPBinary": "qcs615" } } \ No newline at end of file diff --git a/ci/build.sh b/ci/build.sh new file mode 100755 index 0000000..d4f890d --- /dev/null +++ b/ci/build.sh @@ -0,0 +1,66 @@ +#!/usr/bin/bash +# Copyright (c) Qualcomm Technologies, Inc. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +set -euo pipefail + +echo "Configuring APT for amd64 + arm64 (ports)..." +# Detect Ubuntu codename +CODENAME="$(. /etc/os-release; echo "${VERSION_CODENAME}")" +: "${CODENAME:?Failed to read VERSION_CODENAME from /etc/os-release}" +echo "Detected Ubuntu codename: ${CODENAME}" + +# 1) Enable ARM64 multiarch +sudo dpkg --add-architecture arm64 + +# 2) Overwrite main sources to be amd64-only (archive + security) +sudo tee /etc/apt/sources.list > /dev/null < /dev/null < Tue, 09 Jun 2026 13:23:26 +0000 + [ GitHub Service Bot ] + * New upstream release + + -- GitHub Service Bot Thu, 02 Jul 2026 18:30:16 +0000 diff --git a/files/60-fastrpc.rules b/files/60-fastrpc.rules new file mode 100644 index 0000000..546de35 --- /dev/null +++ b/files/60-fastrpc.rules @@ -0,0 +1,19 @@ +# Applications that use libfastrpc must belong to the fastrpc group + +# DMA heap access required for fastrpc +ACTION=="add", SUBSYSTEM=="dma_heap", KERNEL=="system", RUN+="/bin/setfacl -m g:fastrpc:rw $env{DEVNAME}" + +# FastRPC DSP device nodes +# Device nodes are owned by root:fastrpc with 0640 permissions +ACTION=="add", SUBSYSTEM=="misc", KERNEL=="fastrpc-adsp", OWNER="root", GROUP="fastrpc", MODE="0640", TAG+="systemd", ENV{SYSTEMD_WANTS}+="adsprpcd.service", ENV{SYSTEMD_WANTS}+="adsprpcd_audiopd.service" +ACTION=="add", SUBSYSTEM=="misc", KERNEL=="fastrpc-adsp-secure", TAG+="systemd", ENV{SYSTEMD_WANTS}+="adsprpcd.service", ENV{SYSTEMD_WANTS}+="adsprpcd_audiopd.service" +ACTION=="add", SUBSYSTEM=="misc", KERNEL=="fastrpc-cdsp", OWNER="root", GROUP="fastrpc", MODE="0640", TAG+="systemd", ENV{SYSTEMD_WANTS}+="cdsprpcd.service" +ACTION=="add", SUBSYSTEM=="misc", KERNEL=="fastrpc-cdsp-secure", TAG+="systemd", ENV{SYSTEMD_WANTS}+="cdsprpcd.service" +ACTION=="add", SUBSYSTEM=="misc", KERNEL=="fastrpc-cdsp1", OWNER="root", GROUP="fastrpc", MODE="0640", TAG+="systemd", ENV{SYSTEMD_WANTS}+="cdsp1rpcd.service" +ACTION=="add", SUBSYSTEM=="misc", KERNEL=="fastrpc-cdsp1-secure", TAG+="systemd", ENV{SYSTEMD_WANTS}+="cdsp1rpcd.service" +ACTION=="add", SUBSYSTEM=="misc", KERNEL=="fastrpc-gdsp0", OWNER="root", GROUP="fastrpc", MODE="0640", TAG+="systemd", ENV{SYSTEMD_WANTS}+="gdsp0rpcd.service" +ACTION=="add", SUBSYSTEM=="misc", KERNEL=="fastrpc-gdsp0-secure", TAG+="systemd", ENV{SYSTEMD_WANTS}+="gdsp0rpcd.service" +ACTION=="add", SUBSYSTEM=="misc", KERNEL=="fastrpc-gdsp1", OWNER="root", GROUP="fastrpc", MODE="0640", TAG+="systemd", ENV{SYSTEMD_WANTS}+="gdsp1rpcd.service" +ACTION=="add", SUBSYSTEM=="misc", KERNEL=="fastrpc-gdsp1-secure", TAG+="systemd", ENV{SYSTEMD_WANTS}+="gdsp1rpcd.service" +ACTION=="add", SUBSYSTEM=="misc", KERNEL=="fastrpc-sdsp", OWNER="root", GROUP="fastrpc", MODE="0640", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sdsprpcd.service" +ACTION=="add", SUBSYSTEM=="misc", KERNEL=="fastrpc-sdsp-secure", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sdsprpcd.service" diff --git a/files/Makefile.am b/files/Makefile.am new file mode 100644 index 0000000..31a8b3d --- /dev/null +++ b/files/Makefile.am @@ -0,0 +1,41 @@ +# Systemd service files + +# Define systemd unit directory +systemdsystemunitdir = @systemdsystemunitdir@ + +# List of systemd service files to install (generated from .in templates) +systemdsystemunit_DATA = \ + adsprpcd.service \ + adsprpcd_audiopd.service \ + cdsprpcd.service \ + cdsp1rpcd.service \ + gdsp0rpcd.service \ + gdsp1rpcd.service \ + sdsprpcd.service + +# Service template files +EXTRA_DIST = \ + adsprpcd.service.in \ + adsprpcd_audiopd.service.in \ + cdsprpcd.service.in \ + cdsp1rpcd.service.in \ + gdsp0rpcd.service.in \ + gdsp1rpcd.service.in \ + sdsprpcd.service.in + +# Generate service files from templates with sed substitution +%.service: %.service.in Makefile + $(AM_V_GEN)$(SED) \ + -e 's|@sbindir[@]|$(sbindir)|g' \ + $< > $@ + +# Clean generated service files +CLEANFILES = $(systemdsystemunit_DATA) + +# sysusers.d file for creating fastrpc group +sysusersdir = @sysusersdir@ +dist_sysusers_DATA = fastrpc.conf + +# udev rules +udevrulesdir = @udevrulesdir@ +dist_udevrules_DATA = 60-fastrpc.rules diff --git a/files/adsprpcd.service.in b/files/adsprpcd.service.in new file mode 100644 index 0000000..a16e136 --- /dev/null +++ b/files/adsprpcd.service.in @@ -0,0 +1,11 @@ +[Unit] +Description=aDSP RPC daemon +After=dev-fastrpc\x2dadsp.device dev-fastrpc\x2dadsp\x2dsecure.device +ConditionPathExists=|/dev/fastrpc-adsp +ConditionPathExists=|/dev/fastrpc-adsp-secure + +[Service] +Type=exec +ExecStart=@sbindir@/adsprpcd +Restart=on-failure +RestartSec=5 diff --git a/files/adsprpcd_audiopd.service.in b/files/adsprpcd_audiopd.service.in new file mode 100644 index 0000000..617e56e --- /dev/null +++ b/files/adsprpcd_audiopd.service.in @@ -0,0 +1,11 @@ +[Unit] +Description=audiopd aDSP RPC daemon +After=dev-fastrpc\x2dadsp.device dev-fastrpc\x2dadsp\x2dsecure.device +ConditionPathExists=|/dev/fastrpc-adsp +ConditionPathExists=|/dev/fastrpc-adsp-secure + +[Service] +Type=exec +ExecStart=@sbindir@/adsprpcd audiopd +Restart=on-failure +RestartSec=5 diff --git a/files/cdsp1rpcd.service.in b/files/cdsp1rpcd.service.in new file mode 100644 index 0000000..dac5f8d --- /dev/null +++ b/files/cdsp1rpcd.service.in @@ -0,0 +1,11 @@ +[Unit] +Description=cDSP RPC daemon +After=dev-fastrpc\x2dcdsp1.device dev-fastrpc\x2dcdsp1\x2dsecure.device +ConditionPathExists=|/dev/fastrpc-cdsp1 +ConditionPathExists=|/dev/fastrpc-cdsp1-secure + +[Service] +Type=exec +ExecStart=@sbindir@/cdsprpcd rootpd cdsp1 +Restart=on-failure +RestartSec=5 diff --git a/files/cdsprpcd.service.in b/files/cdsprpcd.service.in new file mode 100644 index 0000000..70c4d94 --- /dev/null +++ b/files/cdsprpcd.service.in @@ -0,0 +1,11 @@ +[Unit] +Description=cDSP RPC daemon +After=dev-fastrpc\x2dcdsp.device dev-fastrpc\x2dcdsp\x2dsecure.device +ConditionPathExists=|/dev/fastrpc-cdsp +ConditionPathExists=|/dev/fastrpc-cdsp-secure + +[Service] +Type=exec +ExecStart=@sbindir@/cdsprpcd +Restart=on-failure +RestartSec=5 diff --git a/files/fastrpc.conf b/files/fastrpc.conf new file mode 100644 index 0000000..c55042a --- /dev/null +++ b/files/fastrpc.conf @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-3-Clause +# This file is part of fastrpc. It creates the fastrpc system group. +# +#Type Name ID GECOS Home directory Shell +g fastrpc - - - - diff --git a/files/gdsp0rpcd.service.in b/files/gdsp0rpcd.service.in new file mode 100644 index 0000000..1503941 --- /dev/null +++ b/files/gdsp0rpcd.service.in @@ -0,0 +1,11 @@ +[Unit] +Description=gDSP RPC daemon +After=dev-fastrpc\x2dgdsp0.device dev-fastrpc\x2dgdsp0\x2dsecure.device +ConditionPathExists=|/dev/fastrpc-gdsp0 +ConditionPathExists=|/dev/fastrpc-gdsp0-secure + +[Service] +Type=exec +ExecStart=@sbindir@/gdsprpcd rootpd gdsp0 +Restart=on-failure +RestartSec=5 diff --git a/files/gdsp1rpcd.service.in b/files/gdsp1rpcd.service.in new file mode 100644 index 0000000..66d4bbc --- /dev/null +++ b/files/gdsp1rpcd.service.in @@ -0,0 +1,11 @@ +[Unit] +Description=gDSP RPC daemon +After=dev-fastrpc\x2dgdsp1.device dev-fastrpc\x2dgdsp1\x2dsecure.device +ConditionPathExists=|/dev/fastrpc-gdsp1 +ConditionPathExists=|/dev/fastrpc-gdsp1-secure + +[Service] +Type=exec +ExecStart=@sbindir@/gdsprpcd rootpd gdsp1 +Restart=on-failure +RestartSec=5 diff --git a/files/sdsprpcd.service.in b/files/sdsprpcd.service.in new file mode 100644 index 0000000..150cacf --- /dev/null +++ b/files/sdsprpcd.service.in @@ -0,0 +1,11 @@ +[Unit] +Description=sDSP RPC daemon +After=dev-fastrpc\x2dsdsp.device dev-fastrpc\x2dsdsp\x2dsecure.device +ConditionPathExists=|/dev/fastrpc-sdsp +ConditionPathExists=|/dev/fastrpc-sdsp-secure + +[Service] +Type=exec +ExecStart=@sbindir@/sdsprpcd +Restart=on-failure +RestartSec=5 diff --git a/gitcompile b/gitcompile index 4f8f7d2..3fb6d76 100755 --- a/gitcompile +++ b/gitcompile @@ -2,11 +2,15 @@ autoreconf -is -export CFLAGS='-O2 -Wall -pipe -g' +# Set default build flags if not already set +# Users can override by setting CFLAGS before running this script +if [ -z "$CFLAGS" ]; then + export CFLAGS="-O2 -Wall -pipe -g" +fi + echo "CFLAGS=$CFLAGS" echo "./configure $@" ./configure $@ || exit 1 -unset CFLAGS if [ -z "$GITCOMPILE_NO_MAKE" ]; then make fi diff --git a/inc/Makefile.am b/inc/Makefile.am index dd76127..a22db62 100644 --- a/inc/Makefile.am +++ b/inc/Makefile.am @@ -36,7 +36,6 @@ noinst_HEADERS = \ dspqueue_shared.h \ dspsignal.h \ fastrpc_apps_user.h \ - fastrpc_async.h \ fastrpc_cap.h \ fastrpc_common.h \ fastrpc_config.h \ @@ -45,7 +44,6 @@ noinst_HEADERS = \ fastrpc_hash_table.h \ fastrpc_internal.h \ fastrpc_ioctl.h \ - fastrpc_latency.h \ fastrpc_log.h \ fastrpc_mem.h \ fastrpc_notif.h \ diff --git a/inc/apps_std_internal.h b/inc/apps_std_internal.h index 37be0c2..d4ce4fe 100644 --- a/inc/apps_std_internal.h +++ b/inc/apps_std_internal.h @@ -18,7 +18,6 @@ // Environment variable name, that can be used to override the search paths #define ADSP_LIBRARY_PATH "ADSP_LIBRARY_PATH" #define DSP_LIBRARY_PATH "DSP_LIBRARY_PATH" -#define ADSP_AVS_PATH "ADSP_AVS_CFG_PATH" #define MAX_NON_PRELOAD_LIBS_LEN 2048 #define FILE_EXT ".so" @@ -29,11 +28,6 @@ #define VENDOR_DOM_LOCATION "/vendor/dsp/xdsp/" #endif -// Search path used by fastRPC for acdb path -#ifndef ADSP_AVS_CFG_PATH -#define ADSP_AVS_CFG_PATH ";/etc/acdbdata/;" -#endif - int fopen_from_dirlist(const char *dirList, const char *delim, const char *mode, const char *name, apps_std_FILE *psout); diff --git a/inc/fastrpc_async.h b/inc/fastrpc_async.h deleted file mode 100644 index 76c244d..0000000 --- a/inc/fastrpc_async.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -#ifndef FASTRPC_ASYNC_H -#define FASTRPC_ASYNC_H - -#include "remote64.h" -#include "fastrpc_internal.h" - -#define POS_TO_MASK(pos) ((1UL << pos) - 1) - -#define FASTRPC_ASYNC_JOB_POS 4 // Position in jobid where job starts - -// Store jobs in Queue. Index of queue calculated based on hash value of job. Always needs to be 2^value -#define FASTRPC_ASYNC_QUEUE_LIST_LEN 16 - -// Position where hash ends in jobid -#define FASTRPC_ASYNC_HASH_IDX_POS (FASTRPC_ASYNC_JOB_POS + (FASTRPC_ASYNC_QUEUE_LIST_LEN >> 2)) - -// Position in jobid where timespec starts -#define FASTRPC_ASYNC_TIME_SPEC_POS 48 - -#define SECONDS_PER_HOUR (3600) - -#define FASTRPC_ASYNC_DOMAIN_MASK (POS_TO_MASK(FASTRPC_ASYNC_JOB_POS)) -#define FASTRPC_ASYNC_JOB_CNT_MASK (POS_TO_MASK(FASTRPC_ASYNC_TIME_SPEC_POS) & ~FASTRPC_ASYNC_DOMAIN_MASK) -#define FASTRPC_ASYNC_HASH_MASK (POS_TO_MASK(FASTRPC_ASYNC_HASH_IDX_POS) & ~FASTRPC_ASYNC_DOMAIN_MASK) - -// Async job structure -struct fastrpc_async_job { - uint32_t isasyncjob; // set if async job - /* - * Fastrpc async job ID bit-map: - * - * bits 0-3 : domain ID - * bits 4-47 : job counter - * bits 48-63 : timespec - */ - fastrpc_async_jobid jobid; - uint32_t reserved; // reserved -}; - -/* - * Internal function to save async job information before submitting to DSP - * @ domain: domain to which Async job is submitted - * @ asyncjob: Async job structure - * @ desc: Async desc passed by user - * returns 0 on success - * - */ -int fastrpc_save_async_job(int domain, struct fastrpc_async_job *asyncjob, fastrpc_async_descriptor_t *desc); - -/* - * Internal function to remove async job, if async invocation to DSP fails - * @ jobid: domain to which Async job is submitted - * @ asyncjob: Async job id - * @ dsp_invoke_done: DSP invocation is successful - * returns 0 on success - * - */ -int fastrpc_remove_async_job(fastrpc_async_jobid jobid, bool dsp_invoke_done); - -/* - * API to initialize async module data strcutures and globals - */ -int fastrpc_async_domain_init(int domain); - -/* - * API to de-initialize async module data strcutures and globals - */ -void fastrpc_async_domain_deinit(int domain); - -#endif // FASTRPC_ASYNC_H diff --git a/inc/fastrpc_common.h b/inc/fastrpc_common.h index 1d52afe..709f933 100644 --- a/inc/fastrpc_common.h +++ b/inc/fastrpc_common.h @@ -49,6 +49,10 @@ #define DOMAIN_NAME_IN_URI 1 // Domain name with standard module URI #define DOMAIN_NAME_STAND_ALONE 2 // Stand-alone domain name +/* GDSP domain IDs - internal use only, not part of Hexagon SDK remote.h */ +#define GDSP0_DOMAIN_ID 5 +#define GDSP1_DOMAIN_ID 6 + #define PROFILE(time_taken, ff) \ { \ struct timeval tv1, tv2; \ diff --git a/inc/fastrpc_internal.h b/inc/fastrpc_internal.h index 31f1b5d..920cff9 100644 --- a/inc/fastrpc_internal.h +++ b/inc/fastrpc_internal.h @@ -15,8 +15,8 @@ #include "AEEstd.h" #include "AEEQList.h" #include "AEEStdErr.h" -#include "fastrpc_latency.h" #include "fastrpc_common.h" +#include "fastrpc_ioctl.h" // Aligns the memory #define ALIGN_B(p, a) (((p) + ((a) - 1)) & ~((a) - 1)) @@ -43,8 +43,6 @@ * Update these values for any additions to * the corresponding enums. **/ -/* Max value of fastrpc_async_notify_type, used to validate the user input */ -#define FASTRPC_ASYNC_TYPE_MAX FASTRPC_ASYNC_POLL + 1 /* Max value of remote_dsp_attributes, used to validate the attribute ID*/ #define FASTRPC_MAX_DSP_ATTRIBUTES MCID_MULTICAST + 1 @@ -190,7 +188,6 @@ enum fastrpc_control_type { FASTRPC_CONTROL_WAKELOCK = 4, FASTRPC_CONTROL_PM = 5, FASTRPC_CONTROL_RPC_POLL = 7, - FASTRPC_CONTROL_ASYNC_WAKE = 8, FASTRPC_CONTROL_NOTIF_WAKE = 9, }; @@ -308,7 +305,7 @@ struct handle_list { remote_handle64 remotectlhandle; remote_handle64 adspperfhandle; int procattrs; - struct fastrpc_latency qos; + int adaptive_qos; struct fastrpc_thread_params th_params; int unsigned_module; bool pd_dump; @@ -316,11 +313,8 @@ struct handle_list { int disable_exit_logs; struct fastrpc_dsp_capabilities cap_info; int trace_marker_fd; - uint64_t jobid; /* Capability flag to check if mapping DMA handle through reverse RPC is supported */ int dma_handle_reverse_rpc_map_capability; - /* Mutex to synchronize ASync init and deinit */ - pthread_mutex_t async_init_deinit_mut; uint32_t pd_initmem_size; /** Initial memory allocated for remote userPD */ uint32_t refs; // Number of multi-domain handles + contexts on session bool is_session_reserved; /** Set if session is reserved or used */ @@ -367,21 +361,6 @@ int fastrpc_get_cap(uint32_t domain, uint32_t attributeID, uint32_t *capability) **/ int check_rpc_error(int err); -/** - * @brief Notify the FastRPC QoS logic of activity outside of the invoke code path - * that should still be considered in QoS timeout calculations. - * Note that the function will silently fail on errors such as the domain - * not having a valid QoS mode. - * - * @param[in] domain DSP domain - **/ -void fastrpc_qos_activity(int domain); - -/** - * @brief Make IOCTL call to exit async thread - */ -int fastrpc_exit_async_thread(int domain); - /** * @brief Make IOCTL call to exit notif thread */ @@ -471,6 +450,14 @@ static __inline int convert_kernel_to_user_error(int nErr, int err_no) { return nErr; } +/** + * @brief Get both secure and non-secure device names for a domain + * @param domain_id: Domain ID + * @param secure_name: Output pointer for secure device name + * @param non_secure_name: Output pointer for non-secure device name + **/ +void get_domain_device_names(int domain_id, const char **secure_name, const char **non_secure_name); + /** * @brief utility APIs used in fastRPC library to get name, handle from domain **/ @@ -502,8 +489,7 @@ int fastrpc_update_module_list(uint32_t req, int domain, remote_handle64 handle, * @brief functions to wrap ioctl syscalls for downstream and upstream kernel **/ int ioctl_init(int dev, uint32_t flags, int attr, unsigned char* shell, int shelllen, int shellfd, char* initmem, int initmemlen, int initmemfd, int tessiglen); -int ioctl_invoke(int dev, int req, remote_handle handle, uint32_t sc, void* pra, int* fds, unsigned int* attrs, void *job, unsigned int* crc, uint64_t* perf_kernel, uint64_t* perf_dsp); -int ioctl_invoke2_response(int dev, fastrpc_async_jobid *jobid, remote_handle *handle, uint32_t *sc, int* result, uint64_t *perf_kernel, uint64_t *perf_dsp); +int ioctl_invoke(int dev, int req, remote_handle handle, uint32_t sc, void* pra, int* fds, unsigned int* attrs, unsigned int* crc, uint64_t* perf_kernel, uint64_t* perf_dsp); int ioctl_invoke2_notif(int dev, int *domain, int *session, int *status); int ioctl_mmap(int dev, int req, uint32_t flags, int attr, int fd, int offset, size_t len, uintptr_t vaddrin, uint64_t* vaddr_out); int ioctl_munmap(int dev, int req, int attr, void* buf, int fd, int len, uint64_t vaddr); @@ -538,9 +524,4 @@ int ioctl_optimization(int dev, uint32_t max_concurrency); int ioctl_mdctx_manage(int dev, int req, void *user_ctx, unsigned int *domain_ids, unsigned int num_domain_ids, uint64_t *ctx); -const char* get_secure_domain_name(int domain_id); -int is_async_fastrpc_supported(void); - -#include "fastrpc_ioctl.h" - #endif // FASTRPC_INTERNAL_H diff --git a/inc/fastrpc_ioctl.h b/inc/fastrpc_ioctl.h index 779d034..b9cee80 100644 --- a/inc/fastrpc_ioctl.h +++ b/inc/fastrpc_ioctl.h @@ -43,24 +43,6 @@ #define FASTRPC_ATTR_NOVA (256) -/* Secure and default device nodes */ -#if DEFAULT_DOMAIN_ID==ADSP_DOMAIN_ID - #define SECURE_DEVICE "/dev/fastrpc-adsp-secure" - #define DEFAULT_DEVICE "/dev/fastrpc-adsp" -#elif DEFAULT_DOMAIN_ID==MDSP_DOMAIN_ID - #define SECURE_DEVICE "/dev/fastrpc-mdsp-secure" - #define DEFAULT_DEVICE "/dev/fastrpc-mdsp" -#elif DEFAULT_DOMAIN_ID==SDSP_DOMAIN_ID - #define SECURE_DEVICE "/dev/fastrpc-sdsp-secure" - #define DEFAULT_DEVICE "/dev/fastrpc-sdsp" -#elif DEFAULT_DOMAIN_ID==CDSP_DOMAIN_ID - #define SECURE_DEVICE "/dev/fastrpc-cdsp-secure" - #define DEFAULT_DEVICE "/dev/fastrpc-cdsp" -#else - #define SECURE_DEVICE "" - #define DEFAULT_DEVICE "" -#endif - #define INITIALIZE_REMOTE_ARGS(total) int *pfds = NULL; \ unsigned *pattrs = NULL; \ args = (struct fastrpc_invoke_args*) calloc(sizeof(*args), total); \ diff --git a/inc/fastrpc_latency.h b/inc/fastrpc_latency.h deleted file mode 100644 index caee084..0000000 --- a/inc/fastrpc_latency.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -#ifndef __FASTRPC_LATENCY_H__ -#define __FASTRPC_LATENCY_H__ - -#define FASTRPC_LATENCY_START (1) -#define FASTRPC_LATENCY_STOP (0) -#define FASTRPC_LATENCY_EXIT (2) - -#define SEC_TO_NS (1000000000) -#define MS_TO_US (1000) -#define US_TO_NS MS_TO_US - -#define FASTRPC_LATENCY_VOTE_ON (1) -#define FASTRPC_LATENCY_VOTE_OFF (0) -#define FASTRPC_LATENCY_WAIT_TIME_USEC (100000) -#define FASTRPC_QOS_MAX_LATENCY_USEC (10000) - -/* FastRPC latency voting data for QoS handler of a session */ -struct fastrpc_latency { - int adaptive_qos; - int state; //! latency thread handler running state - int exit; - int invoke; //! invoke count in tacking window - int vote; //! current pm_qos vote status - int dev; //! associated device node - int wait_time; //! wait time for review next voting - int latency; //! user requested fastrpc latency in us - pthread_t thread; - pthread_mutex_t mut; - pthread_mutex_t wmut; - pthread_cond_t cond; -}; - -/* Increment RPC invoke count for activity detection in a window of time - * @param qos, pointer to domain latency data - * return, fastrpc error codes - */ -int fastrpc_latency_invoke_incr(struct fastrpc_latency *qos); - -/* Set qos enable and latency parameters for a configured domain - * @param qos, pointer to domain latency data - * @param enable, qos enable/disable - * @param latency, fastrpc latency requirement from user in us - * @return, fastrpc error codes - */ -int fastrpc_set_pm_qos(struct fastrpc_latency *qos, uint32_t enable, - uint32_t latency); - -/* Initialization routine to initialize globals & internal data structures */ -int fastrpc_latency_init(int dev, struct fastrpc_latency *qos); -/* De-init routine to cleanup globals & internal data structures*/ -int fastrpc_latency_deinit(struct fastrpc_latency *qos); - -#endif /*__FASTRPC_LATENCY_H__*/ diff --git a/inc/fastrpc_mem.h b/inc/fastrpc_mem.h index e4b8667..402f990 100644 --- a/inc/fastrpc_mem.h +++ b/inc/fastrpc_mem.h @@ -73,4 +73,40 @@ int fastrpc_buffer_ref(int domain, int fd, int ref, void **va, size_t *size); */ void remote_register_buf(void *buf, int size, int fd); +/* + * Internal function to map a buffer and return the DSP virtual address. + * Creates a mapping on the DSP and stores the mapping information in the static map list. + * + * @param domain The DSP domain ID (-1 for current domain) + * @param fd File descriptor of the buffer + * @param vaddr Virtual address of the buffer on CPU side + * @param offset Offset from the beginning of the buffer (must be 0) + * @param length Size of buffer in bytes + * @param flags Mapping flags + * @param raddr Output: DSP virtual address of the mapped buffer + * + * @return 0 on success, error code on failure + */ +int fastrpc_mmap_internal(int domain, int fd, void *vaddr, int offset, size_t length, uint32_t flags, uint64_t *raddr); + +/* + * Internal function to unmap a buffer using the DSP virtual address. + * Looks up the mapping in the static map list using the DSP virtual address, + * then performs the unmap operation and removes the mapping from the list. + * + * @param domain The DSP domain ID (-1 for current domain) + * @param raddr DSP virtual address of the mapped buffer + * @param length Size of buffer in bytes to unmap + * + * @return 0 on success, error code on failure + */ +int fastrpc_munmap_internal(int domain, uint64_t raddr, size_t length); + +#define ADSP_MMAP_HEAP_ADDR 4 +#define ADSP_MMAP_REMOTE_HEAP_ADDR 8 +#define ADSP_MMAP_ADD_PAGES 0x1000 +#define ADSP_MMAP_ADD_PAGES_LLC 0x3000 +#define FASTRPC_ALLOC_HLOS_FD \ + 0x10000 /* Flag to allocate HLOS FD to be shared with DSP */ + #endif //FASTRPC_MEM_H diff --git a/inc/remote.h b/inc/remote.h index 1fa3baa..4d4eb8f 100644 --- a/inc/remote.h +++ b/inc/remote.h @@ -122,8 +122,6 @@ extern "C" { #define SDSP_DOMAIN_ID 2 #define CDSP_DOMAIN_ID 3 #define CDSP1_DOMAIN_ID 4 -#define GDSP0_DOMAIN_ID 5 -#define GDSP1_DOMAIN_ID 6 /** Supported Domain Names */ #define ADSP_DOMAIN_NAME "adsp" diff --git a/inc/rpcmem_internal.h b/inc/rpcmem_internal.h index 4fe415e..34aa3eb 100644 --- a/inc/rpcmem_internal.h +++ b/inc/rpcmem_internal.h @@ -6,22 +6,6 @@ #include "rpcmem.h" -/* - * rpcmem_set_dmabuf_name() - API to set name for DMA allocated buffer. - * Name string updates as follows. - * Heap : dsp___ - * Non-heap : apps___ - * - * @name : Pointer to string, "dsp" for heap buffers, "apps" for - * non-heap buffers - * @fd : File descriptor of buffer - * @heapid : Heap ID used for memory allocation - * @buf : Pointer to buffer start address - * @rpcflags: Memory flags describing attributes of allocation - * Return : 0 on success, valid non-zero error code on failure - */ -int rpcmem_set_dmabuf_name(const char *name, int fd, int heapid, - void *buf, uint32_t rpc_flags); /* * returns an file descriptor associated with the address */ diff --git a/public_headers/config.yml b/public_headers/config.yml index c4bd378..7da7b7c 100644 --- a/public_headers/config.yml +++ b/public_headers/config.yml @@ -9,3 +9,12 @@ branches: - inc/remote64.h - inc/dspqueue.h - inc/rpcmem.h + +abi_checks: + - path: src/.libs + include_globs: ["libadsprpc.so", "libcdsprpc.so", "libsdsprpc.so"] + public_headers: + - inc/adsp_default_listener1.h + - inc/HAP_pls.h + - inc/rpcmem.h + - inc/remote.h diff --git a/src/Makefile.am b/src/Makefile.am index 9a3608d..eb80b93 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,11 +1,13 @@ lib_LTLIBRARIES = -LIBDSPRPC_CFLAGS = -fno-short-enums -U_DEBUG -DARM_ARCH_7A -DLE_ENABLE -DENABLE_UPSTREAM_DRIVER_INTERFACE -DUSE_SYSLOG -DCONFIG_BASE_DIR='"$(CONFIG_BASE_DIR)"' -DMACHINE_NAME_PATH='"/sys/firmware/devicetree/base/model"' -I$(top_srcdir)/inc +LIBDSPRPC_CFLAGS = -fno-short-enums -U_DEBUG -DARM_ARCH_7A -DLE_ENABLE -DENABLE_UPSTREAM_DRIVER_INTERFACE -DUSE_SYSLOG -DCONFIG_BASE_DIR='"$(CONFIG_BASE_DIR)"' -DMACHINE_NAME_PATH='"/sys/firmware/devicetree/base/model"' -I$(top_srcdir)/inc @STRICTER_CFLAGS@ @STRICTER_CPPFLAGS@ + +LIBDSPRPC_LDFLAGS = @STRICTER_LDFLAGS@ if ANDROID_CC LIBDSPRPC_CFLAGS += -DDEFAULT_DSP_SEARCH_PATHS='";/vendor/lib/rfsa/adsp;/vendor/dsp;"' else -LIBDSPRPC_CFLAGS += -DPARSE_YAML @YAML_CFLAGS@ -DDEFAULT_DSP_SEARCH_PATHS='";/usr/lib/rfsa/adsp;/usr/lib/dsp;"' +LIBDSPRPC_CFLAGS += -DPARSE_YAML @YAML_CFLAGS@ @BSD_CFLAGS@ -DDEFAULT_DSP_SEARCH_PATHS='";/usr/lib/rfsa/adsp;/usr/lib/dsp;"' endif LIBDSPRPC_SOURCES = \ @@ -13,10 +15,8 @@ LIBDSPRPC_SOURCES = \ fastrpc_perf.c \ fastrpc_pm.c \ fastrpc_config.c \ - fastrpc_async.c \ fastrpc_mem.c \ fastrpc_notif.c \ - fastrpc_latency.c \ fastrpc_ioctl.c \ fastrpc_log.c \ fastrpc_procbuf.c \ @@ -68,64 +68,52 @@ LIBDEFAULT_LISTENER_SOURCES = \ if ANDROID_CC USE_LOG = -llog else -# Add YAML libs to link flags for non-Android builds -libadsprpc_la_LIBADD = @YAML_LIBS@ -libcdsprpc_la_LIBADD = @YAML_LIBS@ -libsdsprpc_la_LIBADD = @YAML_LIBS@ -libgdsprpc_la_LIBADD = @YAML_LIBS@ +# Add YAML and BSD libs to link flags for non-Android builds +libadsprpc_la_LIBADD = -ldl -lm $(USE_LOG) @YAML_LIBS@ @BSD_LIBS@ +libcdsprpc_la_LIBADD = -ldl -lm $(USE_LOG) @YAML_LIBS@ @BSD_LIBS@ +libsdsprpc_la_LIBADD = -ldl -lm $(USE_LOG) @YAML_LIBS@ @BSD_LIBS@ endif ADSP_CFLAGS = $(LIBDSPRPC_CFLAGS) -DDEFAULT_DOMAIN_ID=0 lib_LTLIBRARIES += libadsprpc.la libadsprpc_la_SOURCES = $(LIBDSPRPC_SOURCES) -libadsprpc_la_LDFLAGS = -ldl -lm $(USE_LOG) -version-number @LT_VERSION_NUMBER@ +libadsprpc_la_LDFLAGS = -version-number @LT_VERSION_NUMBER@ $(LIBDSPRPC_LDFLAGS) libadsprpc_la_CFLAGS = $(ADSP_CFLAGS) lib_LTLIBRARIES += libadsp_default_listener.la libadsp_default_listener_la_SOURCES = $(LIBDEFAULT_LISTENER_SOURCES) libadsp_default_listener_la_DEPENDENCIES = libadsprpc.la -libadsp_default_listener_la_LDFLAGS = libadsprpc.la -shared -module $(USE_LOG) -version-number @LT_VERSION_NUMBER@ +libadsp_default_listener_la_LDFLAGS = libadsprpc.la -shared -module $(USE_LOG) -version-number @LT_VERSION_NUMBER@ $(LIBDSPRPC_LDFLAGS) libadsp_default_listener_la_CFLAGS = $(ADSP_CFLAGS) -DUSE_SYSLOG CDSP_CFLAGS = $(LIBDSPRPC_CFLAGS) -DDEFAULT_DOMAIN_ID=3 lib_LTLIBRARIES += libcdsprpc.la libcdsprpc_la_SOURCES = $(LIBDSPRPC_SOURCES) -libcdsprpc_la_LDFLAGS = -ldl -lm $(USE_LOG) -version-number @LT_VERSION_NUMBER@ +libcdsprpc_la_LDFLAGS = -version-number @LT_VERSION_NUMBER@ $(LIBDSPRPC_LDFLAGS) libcdsprpc_la_CFLAGS = $(CDSP_CFLAGS) lib_LTLIBRARIES += libcdsp_default_listener.la libcdsp_default_listener_la_SOURCES = $(LIBDEFAULT_LISTENER_SOURCES) libcdsp_default_listener_la_DEPENDENCIES = libcdsprpc.la -libcdsp_default_listener_la_LDFLAGS = libcdsprpc.la -shared -module $(USE_LOG) -version-number @LT_VERSION_NUMBER@ +libcdsp_default_listener_la_LDFLAGS = libcdsprpc.la -shared -module $(USE_LOG) -version-number @LT_VERSION_NUMBER@ $(LIBDSPRPC_LDFLAGS) libcdsp_default_listener_la_CFLAGS = $(CDSP_CFLAGS) -DUSE_SYSLOG SDSP_CFLAGS = $(LIBDSPRPC_CFLAGS) -DDEFAULT_DOMAIN_ID=2 lib_LTLIBRARIES += libsdsprpc.la libsdsprpc_la_SOURCES = $(LIBDSPRPC_SOURCES) -libsdsprpc_la_LDFLAGS = -ldl -lm $(USE_LOG) -version-number @LT_VERSION_NUMBER@ +libsdsprpc_la_LDFLAGS = -version-number @LT_VERSION_NUMBER@ $(LIBDSPRPC_LDFLAGS) libsdsprpc_la_CFLAGS = $(SDSP_CFLAGS) lib_LTLIBRARIES += libsdsp_default_listener.la libsdsp_default_listener_la_SOURCES = $(LIBDEFAULT_LISTENER_SOURCES) libsdsp_default_listener_la_DEPENDENCIES = libsdsprpc.la -libsdsp_default_listener_la_LDFLAGS = libsdsprpc.la -shared -module $(USE_LOG) -version-number @LT_VERSION_NUMBER@ +libsdsp_default_listener_la_LDFLAGS = libsdsprpc.la -shared -module $(USE_LOG) -version-number @LT_VERSION_NUMBER@ $(LIBDSPRPC_LDFLAGS) libsdsp_default_listener_la_CFLAGS = $(SDSP_CFLAGS) -DUSE_SYSLOG -GDSP_CFLAGS = $(LIBDSPRPC_CFLAGS) -DDEFAULT_DOMAIN_ID=5 - -libgdsprpc_la_SOURCES = $(LIBDSPRPC_SOURCES) -libgdsprpc_la_LDFLAGS = -ldl -lm $(USE_LOG) -version-number @LT_VERSION_NUMBER@ -libgdsprpc_la_CFLAGS = $(GDSP_CFLAGS) - -libgdsp_default_listener_la_SOURCES = $(LIBDEFAULT_LISTENER_SOURCES) -libgdsp_default_listener_la_DEPENDENCIES = libcdsprpc.la -libgdsp_default_listener_la_LDFLAGS = libcdsprpc.la -shared -module $(USE_LOG) -version-number @LT_VERSION_NUMBER@ -libgdsp_default_listener_la_CFLAGS = $(GDSP_CFLAGS) -DUSE_SYSLOG - -bin_PROGRAMS = adsprpcd cdsprpcd sdsprpcd gdsprpcd +sbin_PROGRAMS = adsprpcd cdsprpcd sdsprpcd gdsprpcd adsprpcddir = $(libdir) adsprpcd_SOURCES = dsprpcd.c @@ -147,9 +135,9 @@ sdsprpcd_DEPENDENCIES = libsdsp_default_listener.la sdsprpcd_CFLAGS = -I$(top_srcdir)/inc -DDEFAULT_DOMAIN_ID=2 -DUSE_SYSLOG -DUSE_SDSP sdsprpcd_LDADD = -ldl $(USE_LOG) - +# GDSP daemon shares CDSP libraries (not a typo) gdsprpcddir = $(libdir) gdsprpcd_SOURCES = dsprpcd.c gdsprpcd_DEPENDENCIES = libcdsp_default_listener.la gdsprpcd_CFLAGS = -I$(top_srcdir)/inc -DDEFAULT_DOMAIN_ID=5 -DUSE_SYSLOG -DUSE_GDSP -gdsprpcd_LDADD = -ldl $(USE_LOG) \ No newline at end of file +gdsprpcd_LDADD = -ldl $(USE_LOG) diff --git a/src/adsp_default_listener.c b/src/adsp_default_listener.c index e37648a..ee3d3fd 100644 --- a/src/adsp_default_listener.c +++ b/src/adsp_default_listener.c @@ -33,20 +33,6 @@ #define POLL_TIMEOUT 10 * 1000 #define EVENT_SIZE ( sizeof (struct inotify_event) ) #define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) ) -#define ADSP_SECURE_DEVICE_NAME "fastrpc-adsp-secure" -#define SDSP_SECURE_DEVICE_NAME "fastrpc-sdsp-secure" -#define MDSP_SECURE_DEVICE_NAME "fastrpc-mdsp-secure" -#define CDSP_SECURE_DEVICE_NAME "fastrpc-cdsp-secure" -#define CDSP1_SECURE_DEVICE_NAME "fastrpc-cdsp1-secure" -#define GDSP0_SECURE_DEVICE_NAME "fastrpc-gdsp0-secure" -#define GDSP1_SECURE_DEVICE_NAME "fastrpc-gdsp1-secure" -#define ADSP_DEVICE_NAME "fastrpc-adsp" -#define SDSP_DEVICE_NAME "fastrpc-sdsp" -#define MDSP_DEVICE_NAME "fastrpc-mdsp" -#define CDSP_DEVICE_NAME "fastrpc-cdsp" -#define CDSP1_DEVICE_NAME "fastrpc-cdsp1" -#define GDSP0_DEVICE_NAME "fastrpc-gdsp0" -#define GDSP1_DEVICE_NAME "fastrpc-gdsp1" // Array of supported domain names and its corresponding ID's. static domain_t supported_domains[] = {{ADSP_DOMAIN_ID, ADSP_DOMAIN}, @@ -70,95 +56,23 @@ static domain_t *get_domain_uri(int domain_id) { return NULL; } -static const char *get_secure_device_name(int domain_id) { - const char *name; - int domain = GET_DOMAIN_FROM_EFFEC_DOMAIN_ID(domain_id); - - switch (domain) { - case ADSP_DOMAIN_ID: - name = ADSP_SECURE_DEVICE_NAME; - break; - case SDSP_DOMAIN_ID: - name = SDSP_SECURE_DEVICE_NAME; - break; - case MDSP_DOMAIN_ID: - name = MDSP_SECURE_DEVICE_NAME; - break; - case CDSP_DOMAIN_ID: - name = CDSP_SECURE_DEVICE_NAME; - break; - case CDSP1_DOMAIN_ID: - name = CDSP1_SECURE_DEVICE_NAME; - break; - case GDSP0_DOMAIN_ID: - name = GDSP0_SECURE_DEVICE_NAME; - break; - case GDSP1_DOMAIN_ID: - name = GDSP1_SECURE_DEVICE_NAME; - break; - default: - name = DEFAULT_DEVICE; - break; - } - - return name; -} - -static const char *get_default_device_name(int domain_id) { - const char *name; - int domain = GET_DOMAIN_FROM_EFFEC_DOMAIN_ID(domain_id); - - switch (domain) { - case ADSP_DOMAIN_ID: - name = ADSP_DEVICE_NAME; - break; - case SDSP_DOMAIN_ID: - name = SDSP_DEVICE_NAME; - break; - case MDSP_DOMAIN_ID: - name = MDSP_DEVICE_NAME; - break; - case CDSP_DOMAIN_ID: - name = CDSP_DEVICE_NAME; - break; - case CDSP1_DOMAIN_ID: - name = CDSP1_DEVICE_NAME; - break; - case GDSP0_DOMAIN_ID: - name = GDSP0_DEVICE_NAME; - break; - case GDSP1_DOMAIN_ID: - name = GDSP1_DEVICE_NAME; - break; - default: - name = DEFAULT_DEVICE; - break; - } - - return name; -} /** * fastrpc_dev_exists() - Check if device exists - * @dev_name: Device name + * @dev_path: Full device path (e.g., "/dev/fastrpc-adsp") * * Return: * True: Device node exists * False: Device node does not exist */ -static bool fastrpc_dev_exists(const char* dev_name) +static bool fastrpc_dev_exists(const char* dev_path) { struct stat buffer; - char *path = NULL; - uint64_t len; - len = snprintf(0, 0, "/dev/%s", dev_name) + 1; - if(NULL == (path = (char *)malloc(len * sizeof(char)))) + if (!dev_path) return false; - snprintf(path, (int)len, "/dev/%s", dev_name); - - return (stat(path, &buffer) == 0); + return (stat(dev_path, &buffer) == 0); } /** @@ -172,13 +86,12 @@ static bool fastrpc_dev_exists(const char* dev_name) static int fastrpc_wait_for_device(int domain) { int inotify_fd = -1, watch_fd = -1, err = 0; - const char *sec_dev_name = NULL, *def_dev_name = NULL; + const char *sec_dev_name = NULL, *non_sec_dev_name = NULL; struct pollfd pfd[1]; - sec_dev_name = get_secure_device_name(domain); - def_dev_name = get_default_device_name(domain); + get_domain_device_names(domain, &sec_dev_name, &non_sec_dev_name); - if (fastrpc_dev_exists(sec_dev_name) || fastrpc_dev_exists(def_dev_name)) + if (fastrpc_dev_exists(sec_dev_name) || fastrpc_dev_exists(non_sec_dev_name)) return 0; inotify_fd = inotify_init(); @@ -194,7 +107,7 @@ static int fastrpc_wait_for_device(int domain) return AEE_EINVALIDFD; } - if (fastrpc_dev_exists(sec_dev_name) || fastrpc_dev_exists(def_dev_name)) + if (fastrpc_dev_exists(sec_dev_name) || fastrpc_dev_exists(non_sec_dev_name)) goto bail; memset(pfd, 0 , sizeof(pfd)); @@ -227,11 +140,21 @@ static int fastrpc_wait_for_device(int domain) /* Loop over all events in the buffer. */ for (char *ptr = buffer; ptr < buffer + len; ptr += sizeof(struct inotify_event) + event->len) { + const char *sec_dev_basename = NULL, *non_sec_dev_basename = NULL; event = (struct inotify_event *) ptr; + + /* Extract just the device name from full path for comparison */ + sec_dev_basename = strrchr(sec_dev_name, '/'); + non_sec_dev_basename = strrchr(non_sec_dev_name, '/'); + + /* Skip the '/' character if found */ + sec_dev_basename++; + non_sec_dev_basename++; + /* Check if the event corresponds to the creation of the device node. */ if (event->wd == watch_fd && (event->mask & IN_CREATE) && - ((strcmp(sec_dev_name, event->name) == 0) || - (strcmp(def_dev_name, event->name) == 0))) { + ((sec_dev_basename && strcmp(sec_dev_basename, event->name) == 0) || + (non_sec_dev_basename && strcmp(non_sec_dev_basename, event->name) == 0))) { /* Device node created, process proceed to open and use it. */ VERIFY_IPRINTF("Device node %s created!\n", event->name); goto bail; /* Exit the loop after device creation is detected. */ diff --git a/src/adspmsgd_printf.c b/src/adspmsgd_printf.c index 787d9c1..18f2102 100644 --- a/src/adspmsgd_printf.c +++ b/src/adspmsgd_printf.c @@ -5,6 +5,12 @@ #include "remote.h" #include +#ifdef __ANDROID__ +#include +#endif +#ifdef USE_SYSLOG +#include +#endif #define LOG_NODE_SIZE 256 #define LOG_FILENAME_SIZE 30 @@ -54,5 +60,11 @@ int adspmsgd_apps_log(const unsigned char *log_message_buffer, return 0; } void adspmsgd_log_message(char *format, char *msg) { - printf("adsprpc:dsp: %s\n", msg); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_VERBOSE,"adsprpc",format, msg); +#elif defined(USE_SYSLOG) + syslog(LOG_INFO,"adsprpc:%s ", msg); +#else + printf("adsprpc:%s\n", msg); +#endif } diff --git a/src/apps_mem_imp.c b/src/apps_mem_imp.c index f288d0a..09d58ba 100644 --- a/src/apps_mem_imp.c +++ b/src/apps_mem_imp.c @@ -17,6 +17,7 @@ #include "remote64.h" #include "rpcmem_internal.h" #include "verify.h" +#include #include #include #include @@ -24,12 +25,6 @@ #include #include "fastrpc_hash_table.h" -#define ADSP_MMAP_HEAP_ADDR 4 -#define ADSP_MMAP_REMOTE_HEAP_ADDR 8 -#define ADSP_MMAP_ADD_PAGES 0x1000 -#define ADSP_MMAP_ADD_PAGES_LLC 0x3000 -#define FASTRPC_ALLOC_HLOS_FD \ - 0x10000 /* Flag to allocate HLOS FD to be shared with DSP */ typedef struct { QList mem_list; @@ -128,8 +123,8 @@ __QAIC_IMPL(apps_mem_request_map64)(int heapid, uint32_t lflags, uint32_t rflags VERIFYC(me, AEE_ERESOURCENOTFOUND); VERIFY(AEE_SUCCESS == (nErr = get_unsigned_pd_attribute(domain, &unsigned_module))); - FASTRPC_ATRACE_BEGIN_L("%s called with rflag 0x%x, lflags 0x%x, len 0x%llx, " - "heapid %d and unsigned PD %d", + FASTRPC_ATRACE_BEGIN_L("%s called with rflag 0x%x, lflags 0x%x, " + "len 0x%" PRIx64 ", heapid %d and unsigned PD %d", __func__, rflags, lflags, len, heapid, unsigned_module); if (unsigned_module) { @@ -149,7 +144,6 @@ __QAIC_IMPL(apps_mem_request_map64)(int heapid, uint32_t lflags, uint32_t rflags VERIFYC(NULL != (buf = rpcmem_alloc_internal(heapid, lflags, len)), AEE_ENORPCMEMORY); VERIFYC(0 < (fd = rpcmem_to_fd_internal(buf)), AEE_EBADFD); - rpcmem_set_dmabuf_name("dsp", fd, heapid, buf, lflags); /* Using FASTRPC_MAP_FD_DELAYED as only HLOS mapping is reqd at this point */ VERIFY(AEE_SUCCESS == (nErr = fastrpc_mmap(domain, fd, buf, 0, len, @@ -177,10 +171,9 @@ __QAIC_IMPL(apps_mem_request_map64)(int heapid, uint32_t lflags, uint32_t rflags AEE_ENORPCMEMORY); fd = rpcmem_to_fd_internal(buf); VERIFYC(fd > 0, AEE_EBADPARM); - rpcmem_set_dmabuf_name("dsp", fd, heapid, buf, lflags); } VERIFY(AEE_SUCCESS == - (nErr = remote_mmap64_internal(fd, rflags, (uint64_t)buf, len, + (nErr = remote_mmap64_internal(fd, rflags, (uint64_t)buf, len, (uint64_t *)vadsp))); pbuf = (uint64_t)buf; *vapps = pbuf; @@ -204,7 +197,7 @@ __QAIC_IMPL(apps_mem_request_map64)(int heapid, uint32_t lflags, uint32_t rflags minfo = NULL; } VERIFY_EPRINTF("Error 0x%x: apps_mem_request_mmap64 failed for fd 0x%x of " - "size %lld (lflags 0x%x, rflags 0x%x)\n", + "size %" PRId64 " (lflags 0x%x, rflags 0x%x)\n", nErr, fd, len, lflags, rflags); } FASTRPC_ATRACE_END(); @@ -236,8 +229,8 @@ __QAIC_IMPL(apps_mem_request_unmap64)(uint64_t vadsp, int domain = get_current_domain(); apps_mem_info *me = NULL; - FASTRPC_ATRACE_BEGIN_L("%s called with vadsp 0x%llx, len 0x%llx", __func__, - vadsp, len); + FASTRPC_ATRACE_BEGIN_L("%s called with vadsp 0x%" PRIx64 ", len 0x%" PRIx64, + __func__, vadsp, len); GET_HASH_NODE(apps_mem_info, domain, me); VERIFYC(me, AEE_ERESOURCENOTFOUND); @@ -283,8 +276,8 @@ __QAIC_IMPL(apps_mem_request_unmap64)(uint64_t vadsp, mfree = NULL; bail: if (nErr != AEE_SUCCESS) { - VERIFY_EPRINTF("Error 0x%x: apps_mem_request_unmap64 failed for size %lld " - "(vadsp 0x%llx)\n", + VERIFY_EPRINTF("Error 0x%x: apps_mem_request_unmap64 failed for size " + "%" PRId64 " (vadsp 0x%" PRIx64 ")\n", nErr, len, vadsp); } FASTRPC_ATRACE_END(); @@ -353,7 +346,7 @@ __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_share_unmap)(uint64_t vadsp, int siz nErr = apps_mem_request_unmap64(vadsp, len1); if (nErr != AEE_SUCCESS) { VERIFY_EPRINTF( - "Error 0x%x: apps_mem_share_unmap failed size %d (vadsp 0x%llx)\n", + "Error 0x%x: apps_mem_share_unmap failed size %d (vadsp 0x%" PRIx64 ")\n", nErr, size, vadsp); } return nErr; diff --git a/src/apps_std_imp.c b/src/apps_std_imp.c index 3a69345..536ea40 100644 --- a/src/apps_std_imp.c +++ b/src/apps_std_imp.c @@ -154,8 +154,8 @@ int apps_std_get_dirinfo(const apps_std_DIR *dir, } else { nErr = ESTALE; VERIFY_EPRINTF( - "Error 0x%x: %s: stale directory handle 0x%llx passed by DSP\n", nErr, - __func__, dir->handle); + "Error 0x%x: %s: stale directory handle 0x%" PRIx64 " passed by DSP\n", + nErr, __func__, dir->handle); goto bail; } bail: @@ -970,20 +970,6 @@ static int get_dirlist_from_env(const char *envvarname, char **ppDirList) { // Append default DSP_SEARCH_PATH to user defined env strlcat(envList, dsp_search_path, envListPrependLen); envListLen = envListPrependLen; - } else if (strncmp(envvarname, ADSP_AVS_PATH, - strlen(ADSP_AVS_PATH)) == 0) { - envListPrependLen = envListLen + strlen(ADSP_AVS_CFG_PATH); - if (envLenGuess < envListPrependLen) { - FREEIF(envListBuf); - VERIFYC(envListBuf = - realloc(envListBuf, sizeof(char) * envListPrependLen), - AEE_ENOMEMORY); - envList = envListBuf; - VERIFY(0 == (nErr = apps_std_getenv(envvarname, envList, - envListPrependLen, &listLen))); - } - strlcat(envList, ADSP_AVS_CFG_PATH, envListPrependLen); - envListLen = envListPrependLen; } } else if (strncmp(envvarname, ADSP_LIBRARY_PATH, strlen(ADSP_LIBRARY_PATH)) == 0 || @@ -991,10 +977,6 @@ static int get_dirlist_from_env(const char *envvarname, char **ppDirList) { strlen(DSP_LIBRARY_PATH)) == 0) { envListLen = listLen = 1 + strlcpy(envListBuf, dsp_search_path, envLenGuess); - } else if (strncmp(envvarname, ADSP_AVS_PATH, - strlen(ADSP_AVS_PATH)) == 0) { - envListLen = listLen = - 1 + strlcpy(envListBuf, ADSP_AVS_CFG_PATH, envLenGuess); } /* @@ -1026,19 +1008,24 @@ int fopen_from_dirlist(const char *dirList, const char *delim, const char *mode, const char *name, apps_std_FILE *psout) { int nErr = AEE_SUCCESS; char *absName = NULL, *dirName = NULL, *pos = NULL; + char *dirListCopy = NULL, *dirListPtr = NULL; uint16_t absNameLen = 0; int domain = GET_DOMAIN_FROM_EFFEC_DOMAIN_ID(get_current_domain()); VERIFYC(NULL != dirList, AEE_EBADPARM); - while (dirList) { - pos = strstr(dirList, delim); - dirName = dirList; + // Make a copy of dirList to avoid modifying caller's buffer + VERIFYC(NULL != (dirListCopy = strdup(dirList)), AEE_ENOMEMORY); + dirListPtr = dirListCopy; + + while (dirListPtr) { + pos = strstr(dirListPtr, delim); + dirName = dirListPtr; if (pos) { *pos = '\0'; - dirList = pos + strlen(delim); + dirListPtr = pos + strlen(delim); } else { - dirList = 0; + dirListPtr = 0; } // Append domain to path @@ -1061,6 +1048,7 @@ int fopen_from_dirlist(const char *dirList, const char *delim, // Success FARF(ALWAYS, "Successfully opened file %s", absName); FREEIF(absName); + FREEIF(dirListCopy); return nErr; } FREEIF(absName); @@ -1087,11 +1075,13 @@ int fopen_from_dirlist(const char *dirList, const char *delim, strlen(TESTSIG_FILE_NAME)) != 0)) FARF(ALWAYS, "Successfully opened file %s", name); FREEIF(absName); + FREEIF(dirListCopy); return nErr; } } bail: FREEIF(absName); + FREEIF(dirListCopy); return nErr; } diff --git a/src/dspqueue/.dirstamp b/src/dspqueue/.dirstamp deleted file mode 100644 index e69de29..0000000 diff --git a/src/dsprpcd.c b/src/dsprpcd.c index 348049a..038c09a 100644 --- a/src/dsprpcd.c +++ b/src/dsprpcd.c @@ -14,6 +14,7 @@ #include #include #include +#include #ifndef ADSP_LISTENER_VERSIONED #define ADSP_LISTENER_VERSIONED "libadsp_default_listener.so.1" @@ -27,6 +28,7 @@ #define SDSP_LISTENER_VERSIONED "libsdsp_default_listener.so.1" #define SDSP_LISTENER_UNVERSIONED "libsdsp_default_listener.so" #endif +/* GDSP uses CDSP libraries (not a typo) */ #ifndef GDSP_LISTENER_VERSIONED #define GDSP_LISTENER_VERSIONED "libcdsp_default_listener.so.1" #define GDSP_LISTENER_UNVERSIONED "libcdsp_default_listener.so" @@ -34,6 +36,64 @@ typedef int (*dsp_default_listener_start_t)(int argc, char *argv[]); +/** + * Prints help information about the daemon. + * @param program_name The name of the program + * @param dsp_name The DSP name (ADSP, CDSP, etc.) + */ +static void print_help(const char *program_name, const char *dsp_name) { + printf("Usage: %s [OPTION]...\n", program_name); + printf("Daemon that establishes a connection to %s.\n", dsp_name); +#ifdef USE_ADSP + printf("If audiopd is passed as an argument to this daemon, it will connect to audio PD on %s.\n", dsp_name); +#endif + printf("If no argument is provided or rootpd is passed, it will connect to root PD on %s.\n\n", dsp_name); + + printf("Functionality:\n"); +#ifdef USE_ADSP + printf(" rootpd:\n"); + printf(" - Exception logging: Facilitates transfer of %s process exception logs\n", dsp_name); + printf(" to the HLOS (High-Level Operating System) logging infrastructure for\n"); + printf(" effective monitoring and debugging\n"); + printf(" - Remote file system access\n"); + printf(" audiopd:\n"); + printf(" - Memory requirements for audio PD dynamic loading\n"); + printf(" - Remote file system access\n\n"); +#elif defined(USE_SDSP) + printf(" rootpd:\n"); + printf(" - Remote file system access\n\n"); +#else + printf(" rootpd:\n"); + printf(" - Exception logging: Facilitates transfer of %s process exception logs\n", dsp_name); + printf(" to the HLOS (High-Level Operating System) logging infrastructure for\n"); + printf(" effective monitoring and debugging\n"); + printf(" - Remote file system access\n\n"); +#endif + + printf("Options:\n"); + printf(" -h, --help display this help and exit\n"); + printf(" start daemon for specific PD and domain\n"); +#ifdef USE_ADSP + printf(" example: %s rootpd adsp\n", program_name); +#elif defined(USE_SDSP) + printf(" example: %s rootpd sdsp\n", program_name); +#elif defined(USE_CDSP) + printf(" example: %s rootpd cdsp (or cdsp1)\n", program_name); +#elif defined(USE_GDSP) + printf(" example: %s rootpd gdsp0 (or gdsp1)\n", program_name); +#endif +#ifndef USE_GDSP + printf(" start daemon for specific PD\n"); + printf(" example: %s rootpd\n", program_name); + printf(" (no arguments) start daemon for root PD (default domain)\n\n"); +#else + printf("\n"); +#endif + + printf("Note that this daemon runs continuously and automatically restarts on errors.\n"); + printf("It exits only when the fastRPC device node is not accessible.\n"); +} + // Result struct for dlopen. struct dlopen_result { void *handle; @@ -91,8 +151,28 @@ int main(int argc, char *argv[]) { lib_unversioned = GDSP_LISTENER_UNVERSIONED; dsp_name = "GDSP"; #else - goto bail; + VERIFY_EPRINTF("daemon exiting %x (no DSP type defined)", nErr); + return nErr; #endif + + // Parse command-line options + static struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + int opt; + while ((opt = getopt_long(argc, argv, "h", long_options, NULL)) != -1) { + switch (opt) { + case 'h': + print_help(argv[0], dsp_name); + return 0; + default: + fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]); + return 1; + } + } + VERIFY_EPRINTF("%s daemon starting", dsp_name); while (1) { @@ -119,7 +199,6 @@ int main(int argc, char *argv[]) { usleep(100000); } - bail: - VERIFY_EPRINTF("daemon exiting %x", nErr); - return nErr; + VERIFY_EPRINTF("daemon exiting %x", nErr); + return nErr; } diff --git a/src/dspsignal.c b/src/dspsignal.c index 01c1c1c..7e3fa88 100644 --- a/src/dspsignal.c +++ b/src/dspsignal.c @@ -219,7 +219,6 @@ AEEResult dspsignal_wait(int domain, uint32_t id, uint32_t timeout_usec) { domain = get_domain(domain); VERIFYC(IS_VALID_EFFECTIVE_DOMAIN_ID(domain), AEE_EBADPARM); VERIFYC((ds = (struct dspsignal_domain_signals *)signals->domain_signals[domain]) != NULL, AEE_EBADSTATE); - fastrpc_qos_activity(domain); FARF(MEDIUM, "%s: Wait signal %u timeout %u", __func__, id, timeout_usec); errno = 0; diff --git a/src/fastrpc_apps_user.c b/src/fastrpc_apps_user.c index f111ccf..e2e7aca 100644 --- a/src/fastrpc_apps_user.c +++ b/src/fastrpc_apps_user.c @@ -52,12 +52,10 @@ #include "apps_std_internal.h" #include "dspsignal.h" #include "fastrpc_apps_user.h" -#include "fastrpc_async.h" #include "fastrpc_cap.h" #include "fastrpc_common.h" #include "fastrpc_config.h" #include "fastrpc_internal.h" -#include "fastrpc_latency.h" #include "fastrpc_log.h" #include "fastrpc_mem.h" #include "fastrpc_notif.h" @@ -216,6 +214,7 @@ extern int perf_v2_dsp; #define MIN_PD_INITMEM_SIZE (3 * 1024 * 1024) #define MAX_PD_INITMEM_SIZE (200 * 1024 * 1024) +#define FASTRPC_QOS_MAX_LATENCY_USEC (10000) #define PM_TIMEOUT_MS 5 enum handle_list_id { @@ -399,7 +398,8 @@ int fastrpc_session_put(int domain) { do { if (hlist) { pthread_mutex_lock(&hlist[domain].mut); - hlist[domain].ref--; + if (hlist[domain].ref > 0) + hlist[domain].ref--; ref = hlist[domain].ref; pthread_mutex_unlock(&hlist[domain].mut); FARF(RUNTIME_RPC_HIGH, "%s, domain %d, state %d, ref %d\n", __func__, domain, @@ -1154,8 +1154,7 @@ static void fastrpc_delete_timer(timer_t *timer) { } int remote_handle_invoke_domain(int domain, remote_handle handle, - fastrpc_async_descriptor_t *desc, uint32_t sc, - remote_arg *pra) { + uint32_t sc, remote_arg *pra) { int dev, total, bufs, handles, i, nErr = 0, wake_lock = 0, rpc_timeout = 0; unsigned req; uint32_t len; @@ -1164,7 +1163,6 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, uint32_t *crc_local = NULL; uint64_t *perf_kernel = NULL; uint64_t *perf_dsp = NULL; - struct fastrpc_async_job asyncjob = {0}, *job = NULL; fastrpc_timer frpc_timer; int trace_marker_fd = hlist[domain].trace_marker_fd; bool trace_enabled = false; @@ -1172,8 +1170,11 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, if (IS_QTF_TRACING_ENABLED(hlist[domain].procattrs) && !IS_STATIC_HANDLE(handle) && trace_marker_fd > 0) { - write(trace_marker_fd, INVOKE_BEGIN_TRACE_STR, invoke_begin_trace_strlen); - trace_enabled = true; + /* Write begin trace marker; only enable tracing if write succeeds. + * This ensures we don't attempt to write an end marker if begin failed. */ + ssize_t ret = write(trace_marker_fd, INVOKE_BEGIN_TRACE_STR, invoke_begin_trace_strlen); + if (ret > 0) + trace_enabled = true; } VERIFY(AEE_SUCCESS == (nErr = fastrpc_session_dev(domain, &dev))); @@ -1208,31 +1209,6 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, INITIALIZE_REMOTE_ARGS(total); - if (desc) { - struct timespec time_spec; - // Check for valid user async descriptor - VERIFYC(desc->type >= FASTRPC_ASYNC_NO_SYNC && - desc->type < FASTRPC_ASYNC_TYPE_MAX, - AEE_EBADPARM); - VERIFYC(!(desc->type == FASTRPC_ASYNC_CALLBACK && desc->cb.fn == NULL), - AEE_EBADPARM); - pthread_mutex_lock(&hlist[domain].async_init_deinit_mut); - if (AEE_SUCCESS != (nErr = fastrpc_async_domain_init(domain))) { - pthread_mutex_unlock(&hlist[domain].async_init_deinit_mut); - goto bail; - } - asyncjob.jobid = ++list->jobid; - pthread_mutex_unlock(&hlist[domain].async_init_deinit_mut); - clock_gettime(CLOCK_MONOTONIC, &time_spec); - asyncjob.jobid = ((((time_spec.tv_sec) / SECONDS_PER_HOUR) - << (FASTRPC_ASYNC_TIME_SPEC_POS / 2)) - << ((FASTRPC_ASYNC_TIME_SPEC_POS + 1) / 2) | - (asyncjob.jobid << FASTRPC_ASYNC_JOB_POS) | domain); - asyncjob.isasyncjob = 1; - fastrpc_save_async_job(domain, &asyncjob, desc); - job = &asyncjob; - } - req = INVOKE; VERIFYC(!(NULL == pra && total > 0), AEE_EBADPARM); for (i = 0; i < bufs; i++) { @@ -1247,11 +1223,6 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, set_args_fd(i, fd); req = INVOKE_FD; } - // AsyncRPC doesn't support Non-ion output buffers - if (asyncjob.isasyncjob && i >= (int)REMOTE_SCALARS_INBUFS(sc)) { - VERIFYM(fd != -1, AEE_EBADPARM, - "AsyncRPC doesn't support Non-ion output buffers"); - } if (nova) { req = INVOKE_ATTRS; append_args_attr(i, FASTRPC_ATTR_NOVA); @@ -1309,7 +1280,7 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, } if (IS_CRC_CHECK_ENABLED(hlist[domain].procattrs) && - (!IS_STATIC_HANDLE(handle)) && !asyncjob.isasyncjob) { + (!IS_STATIC_HANDLE(handle))) { int nInBufs = REMOTE_SCALARS_INBUFS(sc); crc_local = (uint32_t *)calloc(M_CRCLIST, sizeof(uint32_t)); crc_remote = (uint32_t *)calloc(M_CRCLIST, sizeof(uint32_t)); @@ -1335,7 +1306,6 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, } if (!IS_STATIC_HANDLE(handle)) { - fastrpc_latency_invoke_incr(&hlist[domain].qos); if ((rpc_timeout = fastrpc_config_get_rpctimeout()) > 0) { frpc_timer.domain = domain; frpc_timer.sc = sc; @@ -1353,7 +1323,7 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, wake_lock = 0; } // Macros are initializing and destroying pfds and pattrs. - nErr = ioctl_invoke(dev, req, handle, sc, get_args(), pfds, pattrs, job, + nErr = ioctl_invoke(dev, req, handle, sc, get_args(), pfds, pattrs, crc_remote, perf_kernel, perf_dsp); if (nErr) { nErr = convert_kernel_to_user_error(nErr, errno); @@ -1369,7 +1339,7 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, } if (IS_CRC_CHECK_ENABLED(hlist[domain].procattrs) && - (!IS_STATIC_HANDLE(handle)) && !asyncjob.isasyncjob) { + (!IS_STATIC_HANDLE(handle))) { int nInBufs = REMOTE_SCALARS_INBUFS(sc); VERIFYC(crc_local != NULL && crc_remote != NULL, AEE_ENOMEMORY); for (i = nInBufs; i < bufs; i++) @@ -1385,7 +1355,7 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, } if (IS_KERNEL_PERF_ENABLED(hlist[domain].procattrs) && - (!IS_STATIC_HANDLE(handle)) && !asyncjob.isasyncjob) { + (!IS_STATIC_HANDLE(handle))) { VERIFYC(perf_kernel != NULL, AEE_ENOMEMORY); FARF(ALWAYS, "RPCPERF-K H:0x%x SC:0x%x C:%" PRIu64 " F:%" PRIu64 " ns M:%" PRIu64 @@ -1396,7 +1366,7 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, perf_kernel[7], perf_kernel[8]); } if (IS_DSP_PERF_ENABLED(hlist[domain].procattrs) && - (!IS_STATIC_HANDLE(handle)) && !asyncjob.isasyncjob) { + (!IS_STATIC_HANDLE(handle))) { VERIFYC(perf_dsp != NULL, AEE_ENOMEMORY); FARF(ALWAYS, "RPCPERF-D H:0x%x SC:0x%x C:%" PRIu64 " M_H:%" PRIu64 " us M:%" PRIu64 @@ -1413,16 +1383,6 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, fastrpc_perf_update(dev, handle, sc); } bail: - if (asyncjob.isasyncjob) { - if (!nErr) { - FARF(RUNTIME_RPC_HIGH, "adsprpc : %s Async job Queued, job 0x%" PRIx64 "", - __func__, asyncjob.jobid); - desc->jobid = asyncjob.jobid; - } else { - fastrpc_remove_async_job(asyncjob.jobid, false); - desc->jobid = -1; - } - } DESTROY_REMOTE_ARGS(); if (crc_local) { free(crc_local); @@ -1432,11 +1392,11 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, free(crc_remote); crc_remote = NULL; } - if (perf_kernel && !asyncjob.isasyncjob) { + if (perf_kernel) { free(perf_kernel); perf_kernel = NULL; } - if (perf_dsp && !asyncjob.isasyncjob) { + if (perf_dsp) { free(perf_dsp); perf_dsp = NULL; } @@ -1449,7 +1409,10 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, } } if (trace_enabled) { - write(trace_marker_fd, INVOKE_END_TRACE_STR, invoke_end_trace_strlen); + /* Write end trace marker. Store return value to satisfy warn_unused_result, + * but don't check it since trace writes are optional and failures are non-critical. */ + ssize_t ret __attribute__((unused)); + ret = write(trace_marker_fd, INVOKE_END_TRACE_STR, invoke_end_trace_strlen); } if (nErr != AEE_SUCCESS) { if ((nErr == -1) && (errno == ECONNRESET)) { @@ -1475,7 +1438,7 @@ int remote_handle_invoke(remote_handle handle, uint32_t sc, remote_arg *pra) { domain = get_current_domain(); FASTRPC_GET_REF(domain); VERIFY(AEE_SUCCESS == - (nErr = remote_handle_invoke_domain(domain, handle, NULL, sc, pra))); + (nErr = remote_handle_invoke_domain(domain, handle, sc, pra))); bail: FASTRPC_PUT_REF(domain); if (nErr != AEE_SUCCESS) { @@ -1523,7 +1486,7 @@ int remote_handle64_invoke(remote_handle64 local, uint32_t sc, FASTRPC_GET_REF(domain); VERIFY(AEE_SUCCESS == (nErr = get_handle_remote(local, &remote))); VERIFY(AEE_SUCCESS == - (nErr = remote_handle_invoke_domain(domain, remote, NULL, sc, pra))); + (nErr = remote_handle_invoke_domain(domain, remote, sc, pra))); bail: FASTRPC_PUT_REF(domain); if (nErr != AEE_SUCCESS) { @@ -1532,11 +1495,19 @@ int remote_handle64_invoke(remote_handle64 local, uint32_t sc, } if (0 == check_rpc_error(nErr)) { if (get_logger_state(domain)) { - FARF(ERROR, - "Error 0x%x: %s failed for module %s, handle 0x%" PRIx64 - ", method %d on domain %d (sc 0x%x) (errno %s)\n", - nErr, __func__, h->name, local, REMOTE_SCALARS_METHOD(sc), domain, sc, - strerror(errno)); + if (nErr == DSP_AEE_EOFFSET + AEE_ENOSUCHMOD) { + FARF(ALWAYS, + "Warning: %s module %s is not supported on DSP domain %d, handle 0x%" PRIx64 + ", method %d (sc 0x%x) (errno %s)\n", + __func__, h->name, domain, local, REMOTE_SCALARS_METHOD(sc), sc, + strerror(errno)); + } else { + FARF(ERROR, + "Error 0x%x: %s failed for module %s, handle 0x%" PRIx64 + ", method %d on domain %d (sc 0x%x) (errno %s)\n", + nErr, __func__, h->name, local, REMOTE_SCALARS_METHOD(sc), domain, sc, + strerror(errno)); + } } } } @@ -1544,72 +1515,6 @@ int remote_handle64_invoke(remote_handle64 local, uint32_t sc, return nErr; } -int remote_handle_invoke_async(remote_handle handle, - fastrpc_async_descriptor_t *desc, uint32_t sc, - remote_arg *pra) { - int domain = -1, nErr = AEE_SUCCESS, ref = 0; - - VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once())); - - FARF(RUNTIME_RPC_HIGH, "Entering %s, handle %u desc %p sc %X remote_arg %p\n", - __func__, handle, desc, sc, pra); - FASTRPC_ATRACE_BEGIN_L("%s called with handle 0x%x , scalar 0x%x", __func__, - (int)handle, sc); - VERIFYC(handle != (remote_handle)-1, AEE_EINVHANDLE); - - domain = get_current_domain(); - FASTRPC_GET_REF(domain); - VERIFY(AEE_SUCCESS == - (nErr = remote_handle_invoke_domain(domain, handle, desc, sc, pra))); -bail: - FASTRPC_PUT_REF(domain); - if (nErr != AEE_SUCCESS) { - if (0 == check_rpc_error(nErr)) { - FARF(ERROR, - "Error 0x%x: %s failed for handle 0x%x, method %d async type %d on " - "domain %d (sc 0x%x) (errno %s)\n", - nErr, __func__, (int)handle, REMOTE_SCALARS_METHOD(sc), desc->type, - domain, sc, strerror(errno)); - } - } - FASTRPC_ATRACE_END(); - return nErr; -} - -int remote_handle64_invoke_async(remote_handle64 local, - fastrpc_async_descriptor_t *desc, uint32_t sc, - remote_arg *pra) { - remote_handle64 remote = 0; - int nErr = AEE_SUCCESS, domain = -1, ref = 0; - - VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once())); - - FARF(RUNTIME_RPC_HIGH, "Entering %s, handle %llu desc %p sc %X remote_arg %p\n", __func__, - local, desc, sc, pra); - FASTRPC_ATRACE_BEGIN_L("%s called with handle 0x%x , scalar 0x%x", __func__, - (int)local, sc); - VERIFYC(local != (remote_handle64)-1, AEE_EINVHANDLE); - - VERIFY(AEE_SUCCESS == (nErr = get_domain_from_handle(local, &domain))); - FASTRPC_GET_REF(domain); - VERIFY(AEE_SUCCESS == (nErr = get_handle_remote(local, &remote))); - VERIFY(AEE_SUCCESS == - (nErr = remote_handle_invoke_domain(domain, remote, desc, sc, pra))); -bail: - FASTRPC_PUT_REF(domain); - if (nErr != AEE_SUCCESS) { - if (0 == check_rpc_error(nErr)) { - FARF(ERROR, - "Error 0x%x: %s failed for handle 0x%" PRIx64 - ", method %d on domain %d (sc 0x%x) (errno %s)\n", - nErr, __func__, local, REMOTE_SCALARS_METHOD(sc), domain, sc, - strerror(errno)); - } - } - FASTRPC_ATRACE_END(); - return nErr; -} - int listener_android_geteventfd(int domain, int *fd); int remote_handle_open_domain(int domain, const char *name, remote_handle *ph, uint64_t *t_spawn, uint64_t *t_load) { @@ -1661,14 +1566,13 @@ int remote_handle_open_domain(int domain, const char *name, remote_handle *ph, */ if (strstr(pdName, get_domain_from_id(GET_DOMAIN_FROM_EFFEC_DOMAIN_ID(domain))) && strstr(pdName, FASTRPC_SESSION_URI)) { - strlcpy(pdName, pdName, - (strlen(pdName) - - strlen(get_domain_from_id(GET_DOMAIN_FROM_EFFEC_DOMAIN_ID(domain))) - - strlen(FASTRPC_SESSION1_URI) + 1)); + /* Truncate string in place by null-terminating at desired length */ + pdName[strlen(pdName) - + strlen(get_domain_from_id(GET_DOMAIN_FROM_EFFEC_DOMAIN_ID(domain))) - + strlen(FASTRPC_SESSION1_URI)] = '\0'; } else if (strstr(pdName, get_domain_from_id(domain))) { - strlcpy( - pdName, pdName, - (strlen(pdName) - strlen(get_domain_from_id(domain)) + 1)); + /* Truncate string in place by null-terminating at desired length */ + pdName[strlen(pdName) - strlen(get_domain_from_id(domain))] = '\0'; } VERIFYC(MAX_DSPPD_NAMELEN > strlen(pdName), AEE_EBADPARM); strlcpy(hlist[domain].dsppdname, pdName, strlen(pdName) + 1); @@ -1978,18 +1882,13 @@ int remote_handle64_close(remote_handle64 handle) { return nErr; } -static int manage_pm_qos(int domain, remote_handle64 h, uint32_t enable, - uint32_t latency) { - return fastrpc_set_pm_qos(&hlist[domain].qos, enable, latency); -} - static int manage_adaptive_qos(int domain, uint32_t enable) { int nErr = AEE_SUCCESS; remote_handle64 handle = INVALID_HANDLE; /* If adaptive QoS is already enabled/disabled, then just return */ - if ((enable && hlist[domain].qos.adaptive_qos) || - (!enable && !hlist[domain].qos.adaptive_qos)) + if ((enable && hlist[domain].adaptive_qos) || + (!enable && !hlist[domain].adaptive_qos)) return nErr; if (hlist[domain].dev != -1) { @@ -2020,11 +1919,11 @@ static int manage_adaptive_qos(int domain, uint32_t enable) { __func__, enable, domain); goto bail; } else { - hlist[domain].qos.adaptive_qos = ((enable == RPC_ADAPTIVE_QOS) ? 1 : 0); + hlist[domain].adaptive_qos = ((enable == RPC_ADAPTIVE_QOS) ? 1 : 0); } } else { /* If session is not created already, then just set process attribute */ - hlist[domain].qos.adaptive_qos = ((enable == RPC_ADAPTIVE_QOS) ? 1 : 0); + hlist[domain].adaptive_qos = ((enable == RPC_ADAPTIVE_QOS) ? 1 : 0); } if (enable) @@ -2089,14 +1988,6 @@ static int manage_poll_qos(int domain, remote_handle64 h, uint32_t enable, return nErr; } -// Notify FastRPC QoS logic of activity outside of the invoke code path. -// This function needs to be in this file to be able to access hlist. -void fastrpc_qos_activity(int domain) { - if (IS_VALID_EFFECTIVE_DOMAIN_ID(domain) && hlist) { - fastrpc_latency_invoke_incr(&hlist[domain].qos); - } -} - static inline int enable_process_state_notif_on_dsp(int domain) { int nErr = AEE_SUCCESS; remote_handle64 notif_handle = 0; @@ -2113,81 +2004,6 @@ static inline int enable_process_state_notif_on_dsp(int domain) { return nErr; } -/* - * Internal function to get async response from kernel. Waits in kernel until - * response is received from DSP - * @ domain: domain to which Async job is submitted - * @ async_data: IOCTL structure that is sent to kernel to get async response - * job information returns 0 on success - * - */ -int get_remote_async_response(int domain, fastrpc_async_jobid *jobid, - int *result) { - int nErr = AEE_SUCCESS, dev = -1; - uint64_t *perf_kernel = NULL, *perf_dsp = NULL; - fastrpc_async_jobid job = -1; - int res = -1; - remote_handle handle = -1; - uint32_t sc = 0; - - VERIFYC(IS_VALID_EFFECTIVE_DOMAIN_ID(domain), AEE_EBADPARM); - VERIFY(AEE_SUCCESS == (nErr = domain_init(domain, &dev))); - VERIFYM(-1 != dev, AEE_ERPC, "open dev failed\n"); - if (IS_KERNEL_PERF_ENABLED(hlist[domain].procattrs)) { - perf_kernel = (uint64_t *)calloc(PERF_KERNEL_KEY_MAX, sizeof(uint64_t)); - VERIFYC(perf_kernel != NULL, AEE_ENOMEMORY); - } - if (IS_DSP_PERF_ENABLED(hlist[domain].procattrs)) { - perf_dsp = (uint64_t *)calloc(PERF_DSP_KEY_MAX, sizeof(uint64_t)); - VERIFYC(perf_dsp != NULL, AEE_ENOMEMORY); - } - nErr = ioctl_invoke2_response(dev, &job, &handle, &sc, &res, perf_kernel, - perf_dsp); - if (IS_KERNEL_PERF_ENABLED(hlist[domain].procattrs) && - (!IS_STATIC_HANDLE(handle))) { - VERIFYC(perf_kernel != NULL, AEE_ENOMEMORY); - FARF(ALWAYS, - "RPCPERF-K H:0x%x SC:0x%x C:%" PRIu64 " F:%" PRIu64 " ns M:%" PRIu64 - " ns CP:%" PRIu64 " ns L:%" PRIu64 " ns G:%" PRIu64 " ns P:%" PRIu64 - " ns INV:%" PRIu64 " ns INVOKE:%" PRIu64 " ns\n", - handle, sc, perf_kernel[0], perf_kernel[1], perf_kernel[2], - perf_kernel[3], perf_kernel[4], perf_kernel[5], perf_kernel[6], - perf_kernel[7], perf_kernel[8]); - } - if (IS_DSP_PERF_ENABLED(hlist[domain].procattrs) && - (!IS_STATIC_HANDLE(handle))) { - VERIFYC(perf_dsp != NULL, AEE_ENOMEMORY); - FARF(ALWAYS, - "RPCPERF-D H:0x%x SC:0x%x C:%" PRIu64 " M_H:%" PRIu64 " us M:%" PRIu64 - " us G:%" PRIu64 " us INVOKE:%" PRIu64 " us P:%" PRIu64 - " us CACHE:%" PRIu64 " us UM:%" PRIu64 " us " - "UM_H:%" PRIu64 " us R:%" PRIu64 " us E_R:%" PRIu64 - " us J_S_T:%" PRIu64 " us\n", - handle, sc, perf_dsp[0], perf_dsp[1], perf_dsp[2], perf_dsp[3], - perf_dsp[4], perf_dsp[5], perf_dsp[6], perf_dsp[7], perf_dsp[8], - perf_dsp[9], perf_dsp[10], perf_dsp[11]); - } - *jobid = job; - *result = res; - -bail: - if (perf_kernel) { - free(perf_kernel); - perf_kernel = NULL; - } - if (perf_dsp) { - free(perf_dsp); - perf_dsp = NULL; - } - if (nErr) { - FARF(ERROR, - "Error 0x%x: %s failed to get async response data for domain %d errno " - "%s", - nErr, __func__, domain, strerror(errno)); - } - return nErr; -} - /* fastrpc_set_qos_latency: Send user QoS latency requirement to DSP. DSP will use required features to meet the requirement. @@ -2285,7 +2101,6 @@ static int fastrpc_dsp_process_clean(int domain) { int remote_handle_control_domain(int domain, remote_handle64 h, uint32_t req, void *data, uint32_t len) { int nErr = AEE_SUCCESS; - const unsigned int POLL_MODE_PM_QOS_LATENCY = 100; FARF(RUNTIME_RPC_HIGH, "Entering %s, domain %d, handle %llu, req %d, data %p, size %d\n", __func__, domain, h, req, data, len); @@ -2302,8 +2117,6 @@ int remote_handle_control_domain(int domain, remote_handle64 h, uint32_t req, case RPC_DISABLE_QOS: { VERIFY(AEE_SUCCESS == (nErr = manage_adaptive_qos(domain, RPC_DISABLE_QOS))); - VERIFY(AEE_SUCCESS == - (nErr = manage_pm_qos(domain, h, RPC_DISABLE_QOS, lp->latency))); VERIFY(AEE_SUCCESS == (nErr = manage_poll_qos(domain, h, RPC_DISABLE_QOS, lp->latency))); /* Error ignored, currently meeting qos requirement is optional. Consider @@ -2312,19 +2125,12 @@ int remote_handle_control_domain(int domain, remote_handle64 h, uint32_t req, break; } case RPC_PM_QOS: { - VERIFY(AEE_SUCCESS == - (nErr = manage_adaptive_qos(domain, RPC_DISABLE_QOS))); - VERIFY(AEE_SUCCESS == - (nErr = manage_pm_qos(domain, h, RPC_PM_QOS, lp->latency))); - /* Error ignored, currently meeting qos requirement is optional. Consider - * to error out in later targets */ - fastrpc_set_qos_latency(domain, h, lp->latency); + FARF(ALWAYS, "Warning: PM QoS is not supported; ignoring request and returning " + "success for backward compatibility"); break; } case RPC_ADAPTIVE_QOS: { - /* Disable PM QoS if enabled and then enable adaptive QoS */ - VERIFY(AEE_SUCCESS == - (nErr = manage_pm_qos(domain, h, RPC_DISABLE_QOS, lp->latency))); + /* Enable adaptive QoS */ VERIFY(AEE_SUCCESS == (nErr = manage_adaptive_qos(domain, RPC_ADAPTIVE_QOS))); /* Error ignored, currently meeting qos requirement is optional. Consider @@ -2335,13 +2141,6 @@ int remote_handle_control_domain(int domain, remote_handle64 h, uint32_t req, case RPC_POLL_QOS: { VERIFY(AEE_SUCCESS == (nErr = manage_poll_qos(domain, h, RPC_POLL_QOS, lp->latency))); - - /* - * Poll QoS option also enables PM QoS to enable early response from DSP - * and stop the CPU cores from going into deep sleep low power modes. - */ - VERIFY(AEE_SUCCESS == (nErr = manage_pm_qos(domain, h, RPC_PM_QOS, - POLL_MODE_PM_QOS_LATENCY))); break; } default: @@ -2455,7 +2254,7 @@ int remote_handle64_control(remote_handle64 handle, uint32_t req, void *data, static int close_domain_session(int domain) { QNode *pn = NULL, *pnn = NULL; char dlerrstr[255]; - int dlerr = 0, nErr = AEE_SUCCESS; + int dlerr = 0, nErr = AEE_SUCCESS, mut_locked = 0; remote_handle64 proc_handle = 0; FARF(ALWAYS, @@ -2469,13 +2268,16 @@ static int close_domain_session(int domain) { adsp_current_process_exit(); } pthread_mutex_lock(&hlist[domain].lmut); + mut_locked = 1; if (!QList_IsEmpty(&hlist[domain].nql)) { QLIST_NEXTSAFE_FOR_ALL(&hlist[domain].nql, pn, pnn) { struct handle_info *hi = STD_RECOVER_REC(struct handle_info, qn, pn); VERIFYC(NULL != hi, AEE_EINVHANDLE); pthread_mutex_unlock(&hlist[domain].lmut); + mut_locked = 0; remote_handle_close(hi->remote); pthread_mutex_lock(&hlist[domain].lmut); + mut_locked = 1; } } if (!QList_IsEmpty(&hlist[domain].rql)) { @@ -2483,8 +2285,10 @@ static int close_domain_session(int domain) { struct handle_info *hi = STD_RECOVER_REC(struct handle_info, qn, pn); VERIFYC(NULL != hi, AEE_EINVHANDLE); pthread_mutex_unlock(&hlist[domain].lmut); + mut_locked = 0; close_reverse_handle(hi->local, dlerrstr, sizeof(dlerrstr), &dlerr); pthread_mutex_lock(&hlist[domain].lmut); + mut_locked = 1; } } if (!QList_IsEmpty(&hlist[domain].ql)) { @@ -2492,12 +2296,19 @@ static int close_domain_session(int domain) { struct handle_info *hi = STD_RECOVER_REC(struct handle_info, qn, pn); VERIFYC(NULL != hi, AEE_EINVHANDLE); pthread_mutex_unlock(&hlist[domain].lmut); + mut_locked = 0; remote_handle64_close(hi->local); pthread_mutex_lock(&hlist[domain].lmut); + mut_locked = 1; } } pthread_mutex_unlock(&hlist[domain].lmut); + mut_locked = 0; bail: + if (mut_locked) { + pthread_mutex_unlock(&hlist[domain].lmut); + mut_locked = 0; + } if (nErr != AEE_SUCCESS) { FARF(ERROR, "Error 0x%x: %s failed for domain %d (errno %s)", nErr, __func__, domain, strerror(errno)); @@ -3150,7 +2961,6 @@ PL_DEP(gpls); PL_DEP(apps_std); PL_DEP(rpcmem); PL_DEP(listener_android); -PL_DEP(fastrpc_async); static int attach_guestos(int domain) { int attach; @@ -3201,9 +3011,6 @@ static void domain_deinit(int domain) { dspsignal_domain_deinit(domain); listener_android_domain_deinit(domain); hlist[domain].first_revrpc_done = 0; - pthread_mutex_lock(&hlist[domain].async_init_deinit_mut); - fastrpc_async_domain_deinit(domain); - pthread_mutex_unlock(&hlist[domain].async_init_deinit_mut); fastrpc_notif_domain_deinit(domain); fastrpc_clear_handle_list(MULTI_DOMAIN_HANDLE_LIST_ID, domain); fastrpc_clear_handle_list(REVERSE_HANDLE_LIST_ID, domain); @@ -3211,7 +3018,6 @@ static void domain_deinit(int domain) { fastrpc_clear_handle_list(NON_DOMAIN_HANDLE_LIST_ID, domain); } fastrpc_perf_deinit(); - fastrpc_latency_deinit(&hlist[domain].qos); trace_marker_deinit(domain); deinitFileWatcher(domain); adspmsgd_stop(domain); @@ -3249,99 +3055,62 @@ static void domain_deinit(int domain) { pthread_mutex_unlock(&hlist[domain].mut); } -static const char *get_domain_name(int domain_id) { - const char *name; +void get_domain_device_names(int domain_id, const char **secure_name, const char **non_secure_name) { int domain = GET_DOMAIN_FROM_EFFEC_DOMAIN_ID(domain_id); switch (domain) { case ADSP_DOMAIN_ID: - name = ADSPRPC_DEVICE; + *secure_name = ADSPRPC_SECURE_DEVICE; + *non_secure_name = ADSPRPC_DEVICE; break; case SDSP_DOMAIN_ID: - name = SDSPRPC_DEVICE; + *secure_name = SDSPRPC_SECURE_DEVICE; + *non_secure_name = SDSPRPC_DEVICE; break; case MDSP_DOMAIN_ID: - name = MDSPRPC_DEVICE; + *secure_name = MDSPRPC_SECURE_DEVICE; + *non_secure_name = MDSPRPC_DEVICE; break; case CDSP_DOMAIN_ID: - name = CDSPRPC_DEVICE; + *secure_name = CDSPRPC_SECURE_DEVICE; + *non_secure_name = CDSPRPC_DEVICE; break; case CDSP1_DOMAIN_ID: - name = CDSP1RPC_DEVICE; + *secure_name = CDSP1RPC_SECURE_DEVICE; + *non_secure_name = CDSP1RPC_DEVICE; break; case GDSP0_DOMAIN_ID: - name = GDSP0RPC_DEVICE; + *secure_name = GDSP0RPC_SECURE_DEVICE; + *non_secure_name = GDSP0RPC_DEVICE; break; case GDSP1_DOMAIN_ID: - name = GDSP1RPC_DEVICE; + *secure_name = GDSP1RPC_SECURE_DEVICE; + *non_secure_name = GDSP1RPC_DEVICE; break; default: - name = DEFAULT_DEVICE; + FARF(ERROR, "ERROR: %s Invalid domain %d", __func__, domain); + *secure_name = NULL; + *non_secure_name = NULL; break; } - return name; } int open_device_node(int domain_id) { int dev = -1, nErr = 0; int domain = GET_DOMAIN_FROM_EFFEC_DOMAIN_ID(domain_id); int sess_id = GET_SESSION_ID_FROM_DOMAIN_ID(domain_id); + const char *secure_dev = NULL, *non_secure_dev = NULL; - switch (domain) { - case ADSP_DOMAIN_ID: - case SDSP_DOMAIN_ID: - case MDSP_DOMAIN_ID: - dev = open(get_secure_domain_name(domain), O_NONBLOCK); - if ((dev < 0) && (errno == ENOENT)) { - FARF(RUNTIME_RPC_HIGH, - "Device node %s open failed for domain %d (errno %s)," - "falling back to node %s \n", - get_secure_domain_name(domain), domain, strerror(errno), - get_domain_name(domain)); - dev = open(get_domain_name(domain), O_NONBLOCK); - if ((dev < 0) && (errno == ENOENT)) { - FARF(RUNTIME_RPC_HIGH, - "Device node %s open failed for domain %d (errno %s)," - "falling back to node %s \n", - get_domain_name(domain), domain, strerror(errno), DEFAULT_DEVICE); - dev = open(DEFAULT_DEVICE, O_NONBLOCK); - } - } else if ((dev < 0) && (errno == EACCES)) { - // Open the default device node if unable to open the - // secure device node due to permissions - FARF(RUNTIME_RPC_HIGH, - "Device node %s open failed for domain %d (errno %s)," - "falling back to node %s \n", - get_secure_domain_name(domain), domain, strerror(errno), - DEFAULT_DEVICE); - dev = open(DEFAULT_DEVICE, O_NONBLOCK); - } - break; - case CDSP_DOMAIN_ID: - case CDSP1_DOMAIN_ID: - case GDSP0_DOMAIN_ID: - case GDSP1_DOMAIN_ID: - dev = open(get_secure_domain_name(domain), O_NONBLOCK); + if (IS_VALID_DOMAIN_ID(domain)) { + get_domain_device_names(domain, &secure_dev, &non_secure_dev); + dev = open(secure_dev, O_NONBLOCK); if ((dev < 0) && ((errno == ENOENT) || (errno == EACCES))) { FARF(RUNTIME_RPC_HIGH, "Device node %s open failed for domain %d (errno %s)," "falling back to node %s \n", - get_secure_domain_name(domain), domain, strerror(errno), - get_domain_name(domain)); - dev = open(get_domain_name(domain), O_NONBLOCK); - if ((dev < 0) && ((errno == ENOENT) || (errno == EACCES))) { - // Open the default device node if actual device node - // is not present - FARF(RUNTIME_RPC_HIGH, - "Device node %s open failed for domain %d (errno %s)," - "falling back to node %s \n", - get_domain_name(domain), domain, strerror(errno), DEFAULT_DEVICE); - dev = open(DEFAULT_DEVICE, O_NONBLOCK); - } + secure_dev, domain, strerror(errno), non_secure_dev); + dev = open(non_secure_dev, O_NONBLOCK); } - break; - default: - break; } if (dev < 0) FARF(ERROR, @@ -3349,8 +3118,8 @@ int open_device_node(int domain_id) { "dev : %s. (errno %d, %s) (Either the remote processor is down, or " "application does not have permission to access the remote " "processor\n", - nErr, __func__, domain_id, sess_id, get_secure_domain_name(domain), - get_domain_name(domain), errno, strerror(errno)); + nErr, __func__, domain_id, sess_id, secure_dev, + non_secure_dev, errno, strerror(errno)); return dev; } @@ -3367,7 +3136,7 @@ static int get_process_attrs(int domain) { attrs = fastrpc_get_property_int(FASTRPC_PROCESS_ATTRS, 0); attrs |= fastrpc_get_property_int(FASTRPC_PROCESS_ATTRS_PERSISTENT, 0); fastrpc_trace = fastrpc_get_property_int(FASTRPC_DEBUG_TRACE, 0); - attrs |= hlist[domain].qos.adaptive_qos ? FASTRPC_MODE_ADAPTIVE_QOS : 0; + attrs |= hlist[domain].adaptive_qos ? FASTRPC_MODE_ADAPTIVE_QOS : 0; attrs |= hlist[domain].unsigned_module ? FASTRPC_MODE_UNSIGNED_MODULE : 0; attrs |= (hlist[domain].pd_dump | fastrpc_config_is_pddump_enabled()) ? FASTRPC_MODE_ENABLE_PDDUMP @@ -3573,7 +3342,7 @@ void print_process_attrs(int domain) { signedMd = true; pd_initmem_size = hlist[domain].pd_initmem_size; } - if (hlist[domain].qos.adaptive_qos) + if (hlist[domain].adaptive_qos) qos = true; if (hlist[domain].pd_dump | fastrpc_config_is_pddump_enabled()) configPDdump = true; @@ -3956,14 +3725,16 @@ remote_handle64 get_adsp_perf1_handle(int domain) { } static int domain_init(int domain, int *dev) { - int nErr = AEE_SUCCESS, dom = GET_DOMAIN_FROM_EFFEC_DOMAIN_ID(domain); + int nErr = AEE_SUCCESS, dom = GET_DOMAIN_FROM_EFFEC_DOMAIN_ID(domain), mut_locked = 0; remote_handle64 panic_handle = 0; struct err_codes *err_codes_to_send = NULL; pthread_mutex_lock(&hlist[domain].mut); + mut_locked = 1; if (hlist[domain].state != FASTRPC_DOMAIN_STATE_CLEAN) { *dev = hlist[domain].dev; pthread_mutex_unlock(&hlist[domain].mut); + mut_locked = 0; return AEE_SUCCESS; } @@ -4020,12 +3791,11 @@ static int domain_init(int domain, int *dev) { ret); } fastrpc_perf_init(hlist[domain].dev, domain); - VERIFY(AEE_SUCCESS == - (nErr = fastrpc_latency_init(hlist[domain].dev, &hlist[domain].qos))); get_dsp_dma_reverse_rpc_map_capability(domain); hlist[domain].state = FASTRPC_DOMAIN_STATE_INIT; hlist[domain].ref = 0; pthread_mutex_unlock(&hlist[domain].mut); + mut_locked = 0; VERIFY(AEE_SUCCESS == (nErr = listener_android_domain_init( domain, hlist[domain].th_params.update_requested, &hlist[domain].th_params.r_sem))); @@ -4038,6 +3808,10 @@ static int domain_init(int domain, int *dev) { } bail: if (nErr != AEE_SUCCESS) { + if (mut_locked) { + pthread_mutex_unlock(&hlist[domain].mut); + mut_locked = 0; + } domain_deinit(domain); if (hlist) { FARF(ERROR, "Error 0x%x: %s (%d) failed for domain %d (errno %s)\n", nErr, @@ -4077,7 +3851,6 @@ static void fastrpc_apps_user_deinit(void) { pthread_mutex_destroy(&hlist[i].mut); pthread_mutex_destroy(&hlist[i].lmut); pthread_mutex_destroy(&hlist[i].init); - pthread_mutex_destroy(&hlist[i].async_init_deinit_mut); } listener_android_deinit(); free(hlist); @@ -4119,8 +3892,8 @@ static void exit_thread(void *value) { INVALID_HANDLE) { nErr = adsp_current_process1_thread_exit(handle); if (nErr) { - FARF(RUNTIME_RPC_HIGH, "%s: nErr:0x%x, dom:%d, h:0x%llx", __func__, nErr, - domain, handle); + FARF(RUNTIME_RPC_HIGH, "%s: nErr:0x%x, dom:%d, h:0x%" PRIx64, + __func__, nErr, domain, handle); } } else if (domain == DEFAULT_DOMAIN_ID) { nErr = adsp_current_process_thread_exit(); @@ -4152,6 +3925,7 @@ static int fastrpc_apps_user_init(void) { VERIFY(AEE_SUCCESS == (nErr = PL_INIT(gpls))); VERIFY(AEE_SUCCESS == (nErr = PL_INIT(rpcmem))); + VERIFY(AEE_SUCCESS == (nErr = PL_INIT(apps_std))); VERIFY(AEE_SUCCESS == (nErr = pthread_key_create(&tlsKey, exit_thread))); #ifdef PARSE_YAML configure_dsp_paths(); @@ -4166,7 +3940,6 @@ static int fastrpc_apps_user_init(void) { FOR_EACH_EFFECTIVE_DOMAIN_ID(i) { hlist[i].dev = -1; hlist[i].th_params.thread_priority = DEFAULT_UTHREAD_PRIORITY; - hlist[i].jobid = 1; hlist[i].info = -1; hlist[i].th_params.stack_size = DEFAULT_UTHREAD_STACK_SIZE; sem_init(&hlist[i].th_params.r_sem, 0, @@ -4183,10 +3956,8 @@ static int fastrpc_apps_user_init(void) { pthread_mutex_init(&hlist[i].mut, &attr); pthread_mutex_init(&hlist[i].lmut, 0); pthread_mutex_init(&hlist[i].init, 0); - pthread_mutex_init(&hlist[i].async_init_deinit_mut, 0); } listener_android_init(); - VERIFY(AEE_SUCCESS == (nErr = PL_INIT(apps_std))); GenCrc32Tab(POLY32, crc_table); fastrpc_notif_init(); apps_mem_table_init(); diff --git a/src/fastrpc_async.c b/src/fastrpc_async.c deleted file mode 100644 index c3b69e5..0000000 --- a/src/fastrpc_async.c +++ /dev/null @@ -1,489 +0,0 @@ -// Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -#ifndef VERIFY_PRINT_ERROR -#define VERIFY_PRINT_ERROR -#endif /* VERIFY_PRINT_ERROR */ - -#define FARF_ERROR 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "AEEQList.h" -#include "AEEStdErr.h" -#include "AEEstd.h" -#include "HAP_farf.h" -#include "fastrpc_perf.h" -#include "fastrpc_common.h" -#include "fastrpc_async.h" -#include "platform_libs.h" -#include "verify.h" - -#define GET_DOMAIN_FROM_JOBID(jobid) (jobid & FASTRPC_ASYNC_DOMAIN_MASK) -#define GET_HASH_FROM_JOBID(jobid) \ - ((jobid & FASTRPC_ASYNC_HASH_MASK) >> FASTRPC_ASYNC_JOB_POS) -#define EVENT_COMPLETE 0xff - -struct fastrpc_async { - QList ql[FASTRPC_ASYNC_QUEUE_LIST_LEN]; - pthread_mutex_t mut; - pthread_t thread; - int init_done; - int deinit_started; -}; - -struct fastrpc_async_job_node { - QNode qn; - fastrpc_async_descriptor_t async_desc; - bool isjobdone; - struct pollfd pfd; - int result; -}; - -pthread_mutex_t async_mut = PTHREAD_MUTEX_INITIALIZER; -static struct fastrpc_async lasyncinfo[NUM_DOMAINS_EXTEND]; - -extern void set_thread_context(int domain); -static int get_remote_async_response(int domain, fastrpc_async_jobid *jobid, - int *result); - -int fastrpc_search_async_job(fastrpc_async_jobid jobid, - struct fastrpc_async_job_node **async_node) { - int nErr = AEE_SUCCESS; - int domain, hash; - struct fastrpc_async *me = NULL; - QNode *pn, *pnn; - bool jobfound = false; - struct fastrpc_async_job_node *lasync_node; - - domain = GET_DOMAIN_FROM_JOBID(jobid); - hash = GET_HASH_FROM_JOBID(jobid); - VERIFYC(IS_VALID_EFFECTIVE_DOMAIN_ID(domain), AEE_EBADPARM); - me = &lasyncinfo[domain]; - VERIFYC(me->init_done == 1, AEE_EBADPARM); - pthread_mutex_lock(&me->mut); - QLIST_NEXTSAFE_FOR_ALL(&me->ql[hash], pn, pnn) { - lasync_node = STD_RECOVER_REC(struct fastrpc_async_job_node, qn, pn); - if (lasync_node->async_desc.jobid == jobid) { - jobfound = true; - break; - } - } - pthread_mutex_unlock(&me->mut); - VERIFYC(jobfound, AEE_EBADPARM); - *async_node = lasync_node; -bail: - return nErr; -} - -int fastrpc_async_get_status(fastrpc_async_jobid jobid, int timeout_us, - int *result) { - int nErr = AEE_SUCCESS; - int domain; - struct fastrpc_async *me = NULL; - struct fastrpc_async_job_node *lasync_node = NULL; - eventfd_t event = 0; - - VERIFYC(result != NULL, AEE_EBADPARM); - VERIFY(AEE_SUCCESS == (nErr = fastrpc_search_async_job(jobid, &lasync_node))); - domain = GET_DOMAIN_FROM_JOBID(jobid); - me = &lasyncinfo[domain]; - pthread_mutex_lock(&me->mut); - if (lasync_node->isjobdone) { // If job is done, return result - *result = lasync_node->result; - goto unlock_bail; - } else if (timeout_us == 0) { // If timeout 0, then return PENDING - nErr = AEE_EBUSY; - goto unlock_bail; - } - // If valid timeout(+ve/-ve), create poll event and wait on poll - if (-1 == (lasync_node->pfd.fd = eventfd(0, 0))) { - nErr = AEE_EFAILED; - FARF(ERROR, - "Error 0x%x: %s failed to create poll event for jobid 0x%" PRIx64 - " (%s)\n", - nErr, __func__, jobid, strerror(errno)); - goto unlock_bail; - } - lasync_node->pfd.events = POLLIN; - lasync_node->pfd.revents = 0; - pthread_mutex_unlock(&me->mut); - while (1) { - VERIFYC(0 < poll(&lasync_node->pfd, 1, timeout_us), AEE_EFAILED); - VERIFYC(0 == eventfd_read(lasync_node->pfd.fd, &event), AEE_EFAILED); - if (event) { - break; - } - } - VERIFYC(lasync_node->isjobdone, AEE_EBUSY); - *result = lasync_node->result; - goto bail; -unlock_bail: - pthread_mutex_unlock(&me->mut); -bail: - if (nErr) { - FARF(ERROR, "Error 0x%x: %s failed for jobid 0x%" PRIx64 " (%s)\n", nErr, - __func__, jobid, strerror(errno)); - } - return nErr; -} - -int fastrpc_remove_async_job(fastrpc_async_jobid jobid, - bool dsp_invoke_done) { - int nErr = AEE_SUCCESS; - struct fastrpc_async *me = NULL; - struct fastrpc_async_job_node *lasync_node = NULL; - int domain = -1; - - VERIFY(AEE_SUCCESS == (nErr = fastrpc_search_async_job(jobid, &lasync_node))); - domain = GET_DOMAIN_FROM_JOBID(jobid); - me = &lasyncinfo[domain]; - pthread_mutex_lock(&me->mut); - if (dsp_invoke_done && !lasync_node->isjobdone) { - pthread_mutex_unlock(&me->mut); - nErr = AEE_EBUSY; - goto bail; - } - QNode_DequeueZ(&lasync_node->qn); - pthread_mutex_unlock(&me->mut); - if (lasync_node->async_desc.type == FASTRPC_ASYNC_POLL && - lasync_node->pfd.fd != -1) { - close(lasync_node->pfd.fd); - lasync_node->pfd.fd = -1; - } - free(lasync_node); - lasync_node = NULL; -bail: - if (nErr) { - FARF(ERROR, - "Error 0x%x: %s failed for domain %d and jobid 0x%" PRIx64 " (%s)\n", - nErr, __func__, domain, jobid, strerror(errno)); - } - return nErr; -} - -int fastrpc_release_async_job(fastrpc_async_jobid jobid) { - return fastrpc_remove_async_job(jobid, true); -} - -int fastrpc_save_async_job(int domain, struct fastrpc_async_job *async_job, - fastrpc_async_descriptor_t *desc) { - int nErr = AEE_SUCCESS; - struct fastrpc_async *me = &lasyncinfo[domain]; - struct fastrpc_async_job_node *lasync_job = 0; - int hash = -1; - - VERIFYC(me->init_done == 1, AEE_EINVALIDJOB); - VERIFYC(NULL != (lasync_job = calloc(1, sizeof(*lasync_job))), AEE_ENOMEMORY); - QNode_CtorZ(&lasync_job->qn); - lasync_job->async_desc.jobid = async_job->jobid; - lasync_job->async_desc.type = desc->type; - lasync_job->async_desc.cb.fn = desc->cb.fn; - lasync_job->async_desc.cb.context = desc->cb.context; - lasync_job->isjobdone = false; - lasync_job->result = -1; - lasync_job->pfd.fd = -1; - hash = GET_HASH_FROM_JOBID(lasync_job->async_desc.jobid); - pthread_mutex_lock(&me->mut); - QList_AppendNode(&me->ql[hash], &lasync_job->qn); - pthread_mutex_unlock(&me->mut); - FARF(RUNTIME_RPC_HIGH, "adsprpc: %s : Saving job with jobid 0x%" PRIx64 "", - __func__, lasync_job->async_desc.jobid); -bail: - if (nErr) { - FARF(ERROR, "Error 0x%x: %s failed for domain %d (%s)\n", nErr, __func__, - domain, strerror(errno)); - } - return nErr; -} - -void fastrpc_async_respond_all_pending_jobs(int domain) { - int i = 0; - struct fastrpc_async *me = &lasyncinfo[domain]; - struct fastrpc_async_job_node *lasync_node = NULL; - QNode *pn; - - for (i = 0; i < FASTRPC_ASYNC_QUEUE_LIST_LEN; i++) { - pthread_mutex_lock(&me->mut); - while (!QList_IsEmpty(&me->ql[i])) { - pn = QList_GetFirst(&me->ql[i]); - lasync_node = STD_RECOVER_REC(struct fastrpc_async_job_node, qn, pn); - if (!lasync_node) { - continue; - } - QNode_DequeueZ(&lasync_node->qn); - lasync_node->result = -ECONNRESET; - pthread_mutex_unlock(&me->mut); - if (lasync_node->async_desc.type == FASTRPC_ASYNC_CALLBACK) { - FARF(RUNTIME_RPC_HIGH, - "adsprpc: %s callback jobid 0x%" PRIx64 " and result 0x%x", - __func__, lasync_node->async_desc.jobid, lasync_node->result); - lasync_node->async_desc.cb.fn(lasync_node->async_desc.jobid, - lasync_node->async_desc.cb.context, - lasync_node->result); - } else if (lasync_node->async_desc.type == FASTRPC_ASYNC_POLL) { - FARF(RUNTIME_RPC_HIGH, - "adsprpc: %s poll jobid 0x%" PRIx64 " and result 0x%x", __func__, - lasync_node->async_desc.jobid, lasync_node->result); - if (lasync_node->pfd.fd != -1) { - eventfd_write(lasync_node->pfd.fd, (eventfd_t)EVENT_COMPLETE); - } - } - free(lasync_node); - lasync_node = NULL; - pthread_mutex_lock(&me->mut); - } - pthread_mutex_unlock(&me->mut); - } -} - -static void *async_fastrpc_thread(void *arg) { - int nErr = AEE_SUCCESS; - struct fastrpc_async *me = (struct fastrpc_async *)arg; - int domain = (int)(me - &lasyncinfo[0]); - struct fastrpc_async_job_node *lasync_node = NULL; - int result = -1; - fastrpc_async_jobid jobid = -1; - QNode *pn, *pnn; - - int hash = -1; - bool isjobfound = false; - - /// TODO: Do we really need this line? - set_thread_context(domain); - do { - nErr = get_remote_async_response(domain, &jobid, &result); - VERIFY(nErr == AEE_SUCCESS); - FARF(RUNTIME_RPC_HIGH, - "adsprpc: %s received async response for jobid 0x%" PRIx64 - " and result 0x%x", - __func__, jobid, result); - isjobfound = false; - hash = GET_HASH_FROM_JOBID(jobid); - pthread_mutex_lock(&me->mut); - QLIST_NEXTSAFE_FOR_ALL(&me->ql[hash], pn, pnn) { - lasync_node = STD_RECOVER_REC(struct fastrpc_async_job_node, qn, pn); - if (lasync_node->async_desc.jobid == jobid) { - lasync_node->isjobdone = true; - lasync_node->result = result; - isjobfound = true; - switch (lasync_node->async_desc.type) { - case FASTRPC_ASYNC_NO_SYNC: - FARF(RUNTIME_RPC_HIGH, - "adsprpc: %s nosync jobid 0x%" PRIx64 " and result 0x%x", - __func__, lasync_node->async_desc.jobid, result); - QNode_DequeueZ(&lasync_node->qn); - pthread_mutex_unlock(&me->mut); - free(lasync_node); - lasync_node = NULL; - break; - case FASTRPC_ASYNC_POLL: - FARF(RUNTIME_RPC_HIGH, - "adsprpc: %s poll jobid 0x%" PRIx64 " and result 0x%x", __func__, - lasync_node->async_desc.jobid, result); - if (lasync_node->pfd.fd != -1) { - eventfd_write(lasync_node->pfd.fd, (eventfd_t)EVENT_COMPLETE); - } - pthread_mutex_unlock(&me->mut); - break; - case FASTRPC_ASYNC_CALLBACK: - pthread_mutex_unlock(&me->mut); - FARF(RUNTIME_RPC_HIGH, - "adsprpc: %s callback jobid 0x%" PRIx64 " and result 0x%x", - __func__, lasync_node->async_desc.jobid, result); - lasync_node->async_desc.cb.fn(lasync_node->async_desc.jobid, - lasync_node->async_desc.cb.context, - result); - break; - default: - pthread_mutex_unlock(&me->mut); - FARF(RUNTIME_RPC_HIGH, - "adsprpc: %s Invalid job type for jobid 0x%" PRIx64 "", __func__, - lasync_node->async_desc.jobid); - break; - } - break; - } - } - if (!isjobfound) - pthread_mutex_unlock(&me->mut); - } while (1); -bail: - if (nErr != AEE_SUCCESS) { - VERIFY_EPRINTF("Error 0x%x: %s AsyncFastRPC worker thread exited for " - "domain %d (errno %s), async_domain_deinit started %d", - nErr, __func__, domain, strerror(errno), me->deinit_started); - } - dlerror(); - return (void *)(uintptr_t)nErr; -} - -void async_thread_exit_handler(int sig) { - FARF(ALWAYS, "Async FastRPC worker thread exiting with signal %d\n", sig); - pthread_exit(0); -} - -void fastrpc_async_domain_deinit(int domain) { - struct fastrpc_async *me = &lasyncinfo[domain]; - int err = 0; - - pthread_mutex_lock(&async_mut); - if (!me->init_done) { - goto fasync_deinit_done; - } - FARF(ALWAYS, "%s: Waiting for AsyncRPC worker thread to join for domain %d\n", - __func__, domain); - if (me->thread) { - me->deinit_started = 1; - err = fastrpc_exit_async_thread(domain); - if (err) { - pthread_kill(me->thread, SIGUSR1); - } - pthread_join(me->thread, 0); - me->thread = 0; - } - FARF(ALWAYS, "fastrpc async thread joined for domain %d", domain); - fastrpc_async_respond_all_pending_jobs(domain); - pthread_mutex_destroy(&me->mut); - me->init_done = 0; -fasync_deinit_done: - pthread_mutex_unlock(&async_mut); - return; -} - -int fastrpc_async_domain_init(int domain) { - struct fastrpc_async *me = &lasyncinfo[domain]; - int nErr = AEE_EUNKNOWN, i = 0; - struct sigaction siga; - uint32_t capability = 0; - - pthread_mutex_lock(&async_mut); - if (me->init_done) { - nErr = AEE_SUCCESS; - goto bail; - } - VERIFY(AEE_SUCCESS == - (nErr = fastrpc_get_cap(domain, ASYNC_FASTRPC_SUPPORT, &capability))); - VERIFYC(capability == 1, AEE_EUNSUPPORTED); - me->thread = 0; - pthread_mutex_init(&me->mut, 0); - for (i = 0; i < FASTRPC_ASYNC_QUEUE_LIST_LEN; i++) { - QList_Ctor(&me->ql[i]); - } - VERIFY(AEE_SUCCESS == - (nErr = pthread_create(&me->thread, 0, async_fastrpc_thread, - (void *)me))); - memset(&siga, 0, sizeof(siga)); - siga.sa_flags = 0; - siga.sa_handler = async_thread_exit_handler; - VERIFY(AEE_SUCCESS == (nErr = sigaction(SIGUSR1, &siga, NULL))); - me->init_done = 1; - me->deinit_started = 0; - FARF(ALWAYS, "%s: AsyncRPC worker thread launched for domain %d\n", __func__, - domain); -bail: - pthread_mutex_unlock(&async_mut); - if (nErr != AEE_SUCCESS) { - VERIFY_EPRINTF("Error 0x%x: %s failed for domain %d (%s)\n", nErr, __func__, - domain, strerror(errno)); - fastrpc_async_domain_deinit(domain); - } - return nErr; -} - -/* - * Internal function to get async response from kernel. Waits in kernel until - * response is received from DSP - * @ domain: domain to which Async job is submitted - * @ async_data: IOCTL structure that is sent to kernel to get async response - * job information returns 0 on success - * - */ -static int get_remote_async_response(int domain, fastrpc_async_jobid *jobid, - int *result) { - int nErr = AEE_SUCCESS, dev = -1; - uint64_t *perf_kernel = NULL, *perf_dsp = NULL; - fastrpc_async_jobid job = -1; - int res = -1; - remote_handle handle = -1; - uint32_t sc = 0; - - VERIFYC(IS_VALID_EFFECTIVE_DOMAIN_ID(domain), AEE_EBADPARM); - VERIFY(AEE_SUCCESS == (nErr = fastrpc_session_dev(domain, &dev))); - VERIFYM(-1 != dev, AEE_ERPC, "open dev failed\n"); - if (is_kernel_perf_enabled()) { - perf_kernel = (uint64_t *)calloc(PERF_KERNEL_KEY_MAX, sizeof(uint64_t)); - VERIFYC(perf_kernel != NULL, AEE_ENOMEMORY); - } - if (is_dsp_perf_enabled(domain)) { - perf_dsp = (uint64_t *)calloc(PERF_DSP_KEY_MAX, sizeof(uint64_t)); - VERIFYC(perf_dsp != NULL, AEE_ENOMEMORY); - } - nErr = ioctl_invoke2_response(dev, &job, &handle, &sc, &res, perf_kernel, - perf_dsp); - if (perf_kernel) { - FARF(ALWAYS, - "RPCPERF-K H:0x%x SC:0x%x C:%" PRIu64 " F:%" PRIu64 " ns M:%" PRIu64 - " ns CP:%" PRIu64 " ns L:%" PRIu64 " ns G:%" PRIu64 " ns P:%" PRIu64 - " ns INV:%" PRIu64 " ns INVOKE:%" PRIu64 " ns\n", - handle, sc, perf_kernel[0], perf_kernel[1], perf_kernel[2], - perf_kernel[3], perf_kernel[4], perf_kernel[5], perf_kernel[6], - perf_kernel[7], perf_kernel[8]); - } - if (perf_dsp) { - FARF(ALWAYS, - "RPCPERF-D H:0x%x SC:0x%x C:%" PRIu64 " M_H:%" PRIu64 " us M:%" PRIu64 - " us G:%" PRIu64 " us INVOKE:%" PRIu64 " us P:%" PRIu64 - " us CACHE:%" PRIu64 " us UM:%" PRIu64 " us " - "UM_H:%" PRIu64 " us R:%" PRIu64 " us E_R:%" PRIu64 - " us J_S_T:%" PRIu64 " us\n", - handle, sc, perf_dsp[0], perf_dsp[1], perf_dsp[2], perf_dsp[3], - perf_dsp[4], perf_dsp[5], perf_dsp[6], perf_dsp[7], perf_dsp[8], - perf_dsp[9], perf_dsp[10], perf_dsp[11]); - } - *jobid = job; - *result = res; - -bail: - if (perf_kernel) { - free(perf_kernel); - perf_kernel = NULL; - } - if (perf_dsp) { - free(perf_dsp); - perf_dsp = NULL; - } - if (nErr) { - FARF(ERROR, - "Error 0x%x: %s failed to get async response data for domain %d errno " - "%s", - nErr, __func__, domain, strerror(errno)); - } - return nErr; -} - -// Make IOCTL call to exit async thread -int fastrpc_exit_async_thread(int domain) { - int nErr = AEE_SUCCESS, dev; - - VERIFY(AEE_SUCCESS == (nErr = fastrpc_session_dev(domain, &dev))); - nErr = ioctl_control(dev, DSPRPC_ASYNC_WAKE, NULL); -bail: - if (nErr) - FARF(ERROR, - "Error 0x%x: %s failed for domain %d (errno: %s), ignore if ioctl not " - "supported, try pthread kill ", - nErr, __func__, domain, strerror(errno)); - return nErr; -} diff --git a/src/fastrpc_cap.c b/src/fastrpc_cap.c index 0ad169e..c088a74 100644 --- a/src/fastrpc_cap.c +++ b/src/fastrpc_cap.c @@ -108,12 +108,6 @@ int fastrpc_get_cap(uint32_t domain, uint32_t attributeID, uint32_t *capability) } goto bail; } - if(attributeID == ASYNC_FASTRPC_SUPPORT) { - if(!is_async_fastrpc_supported() ) { - *capability = 0; - goto bail; - } - } VERIFY(AEE_SUCCESS == (nErr = fastrpc_session_open(dom, &dev))); errno = 0; diff --git a/src/fastrpc_config_parser.c b/src/fastrpc_config_parser.c index 786aebe..d832a7b 100644 --- a/src/fastrpc_config_parser.c +++ b/src/fastrpc_config_parser.c @@ -1,181 +1,188 @@ -// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. -// SPDX-License-Identifier: BSD-3-Clause-Clear - -#define _GNU_SOURCE -#ifndef VERIFY_PRINT_WARN -#define VERIFY_PRINT_WARN -#endif // VERIFY_PRINT_WARN -#ifndef VERIFY_PRINT_ERROR_ALWAYS -#define VERIFY_PRINT_ERROR_ALWAYS -#endif // VERIFY_PRINT_ERROR_ALWAYS -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define FARF_ERROR 1 -#define FARF_HIGH 1 -#define FARF_MED 1 -#define FARF_LOW 1 -#define FARF_CRITICAL 1 // Push log's to all hooks and persistent buffer. - -#define CONFIG_DIR CONFIG_BASE_DIR "/conf.d/" - -#include "AEEQList.h" -#include "AEEStdErr.h" -#include "AEEstd.h" -#include "HAP_farf.h" -#include "apps_std_internal.h" -#include "fastrpc_config_parser.h" - -static int compare_strings(const void *a, const void *b) { - return strcmp(*(const char **)a, *(const char **)b); -} - -static void get_dsp_lib_path(const char *machine_name, const char *filepath, char *dsp_lib_paths) { - yaml_parser_t parser; - yaml_event_t event; - int done = 0; - int in_machines = 0; - int in_target_machine = 0; - int found_dsp_path = 0; - char current_machine[PATH_MAX] = {0}; - - FILE *file = fopen(filepath, "r"); - if (!file) - return; - - if (!yaml_parser_initialize(&parser)) { - FARF(ALWAYS, "Warning: Failed to initialize YAML parser for file %s\n", filepath); - fclose(file); - return; - } - - yaml_parser_set_input_file(&parser, file); - - while (!done) { - if (!yaml_parser_parse(&parser, &event)) { - FARF(ALWAYS, "Warning: YAML parser error in file %s\n", filepath); - break; - } - - switch (event.type) { - case YAML_SCALAR_EVENT: { - const char *value = (const char *)event.data.scalar.value; - - if (!in_machines && strcmp(value, "machines") == 0) { - in_machines = 1; - } else if (in_machines && !in_target_machine) { - // This is a machine name key - strlcpy(current_machine, value, sizeof(current_machine)); - if (strcmp(current_machine, machine_name) == 0) { - in_target_machine = 1; - } - } else if (in_target_machine && strcmp(value, DSP_LIB_KEY) == 0) { - // Next scalar will be the DSP_LIBRARY_PATH value - yaml_event_delete(&event); - if (yaml_parser_parse(&parser, &event) && event.type == YAML_SCALAR_EVENT) { - strlcpy(dsp_lib_paths, (const char *)event.data.scalar.value, PATH_MAX); - FARF(ALWAYS, "dsp_lib_paths is %s", dsp_lib_paths); - found_dsp_path = 1; - done = 1; - } - } - break; - } - case YAML_MAPPING_END_EVENT: - if (in_target_machine) { - // Exiting the target machine mapping - in_target_machine = 0; - if (found_dsp_path) { - done = 1; - } - } - break; - case YAML_STREAM_END_EVENT: - done = 1; - break; - default: - break; - } - - yaml_event_delete(&event); - } - - yaml_parser_delete(&parser); - fclose(file); - - if (!found_dsp_path) { - FARF(ALWAYS, "Warning: DSP_LIBRARY_PATH not found for machine [%s] in configuration file %s\n", - machine_name, filepath); - } -} - -static void parse_config_dir(char *machine_name) { - DIR *dir = opendir(CONFIG_DIR); - struct dirent *entry; - char *file_list[1024]; - int file_count = 0; - char dsp_lib_paths[PATH_MAX] = {0}; - - if (!dir) - return; - - while ((entry = readdir(dir)) != NULL) { - if (entry->d_type == DT_REG && - (strstr(entry->d_name, ".yaml") || strstr(entry->d_name, ".yml"))) { - file_list[file_count] = strdup(entry->d_name); - file_count++; - } - } - closedir(dir); - - qsort(file_list, file_count, sizeof(char *), compare_strings); - - for (int i = 0; i < file_count; i++) { - char filepath[PATH_MAX]; - snprintf(filepath, sizeof(filepath), "%s%s", CONFIG_DIR, file_list[i]); - get_dsp_lib_path(machine_name, filepath, dsp_lib_paths); - free(file_list[i]); - } - - if (dsp_lib_paths[0] != '\0') { - strlcpy(DSP_LIBS_LOCATION, CONFIG_BASE_DIR, sizeof(DSP_LIBS_LOCATION)); - //append slash in case user passed config base dir doesn't end with slash '/' - strlcat(DSP_LIBS_LOCATION, "/", sizeof(DSP_LIBS_LOCATION)); - strlcat(DSP_LIBS_LOCATION, dsp_lib_paths, sizeof(DSP_LIBS_LOCATION)); - strlcat(DSP_LIBS_LOCATION, DEFAULT_DSP_SEARCH_PATHS, sizeof(DSP_LIBS_LOCATION)); - } else { - FARF(ALWAYS, "Warning: No DSP library path found for machine [%s] in any configuration file\n", - machine_name); - } -} - -void configure_dsp_paths() { - char machine_name[PATH_MAX] = {0}; - FILE *file = fopen(MACHINE_NAME_PATH, "r"); - - if (file == NULL) - return; - - if (fgets(machine_name, sizeof(machine_name), file) != NULL) - // Remove trailing newline if present - machine_name[strcspn(machine_name, "\n")] = '\0'; - - fclose(file); - parse_config_dir(machine_name); -} +// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +// SPDX-License-Identifier: BSD-3-Clause-Clear + +#define _GNU_SOURCE +#ifndef VERIFY_PRINT_WARN +#define VERIFY_PRINT_WARN +#endif // VERIFY_PRINT_WARN +#ifndef VERIFY_PRINT_ERROR_ALWAYS +#define VERIFY_PRINT_ERROR_ALWAYS +#endif // VERIFY_PRINT_ERROR_ALWAYS +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FARF_ERROR 1 +#define FARF_HIGH 1 +#define FARF_MED 1 +#define FARF_LOW 1 +#define FARF_CRITICAL 1 // Push log's to all hooks and persistent buffer. + +#define CONFIG_DIR CONFIG_BASE_DIR "/conf.d/" + +#include "AEEQList.h" +#include "AEEStdErr.h" +#include "AEEstd.h" +#include "HAP_farf.h" +#include "apps_std_internal.h" +#include "fastrpc_config_parser.h" + +static int compare_strings(const void *a, const void *b) { + return strcmp(*(const char **)a, *(const char **)b); +} + +static void get_dsp_lib_path(const char *machine_name, const char *filepath, char *dsp_lib_paths) { + yaml_parser_t parser; + yaml_event_t event; + int done = 0; + int in_machines = 0; + int in_target_machine = 0; + int found_dsp_path = 0; + char current_machine[PATH_MAX] = {0}; + + FILE *file = fopen(filepath, "r"); + if (!file) + return; + + if (!yaml_parser_initialize(&parser)) { + FARF(ALWAYS, "Warning: Failed to initialize YAML parser for file %s\n", filepath); + fclose(file); + return; + } + + yaml_parser_set_input_file(&parser, file); + + while (!done) { + if (!yaml_parser_parse(&parser, &event)) { + FARF(ALWAYS, "Warning: YAML parser error in file %s\n", filepath); + break; + } + + switch (event.type) { + case YAML_SCALAR_EVENT: { + const char *value = (const char *)event.data.scalar.value; + + if (!in_machines && strcmp(value, "machines") == 0) { + in_machines = 1; + } else if (in_machines && !in_target_machine) { + // This is a machine name key + strlcpy(current_machine, value, sizeof(current_machine)); + if (strcmp(current_machine, machine_name) == 0) { + in_target_machine = 1; + } + } else if (in_target_machine && strcmp(value, DSP_LIB_KEY) == 0) { + // Next scalar will be the DSP_LIBRARY_PATH value + yaml_event_delete(&event); + if (yaml_parser_parse(&parser, &event) && event.type == YAML_SCALAR_EVENT) { + strlcpy(dsp_lib_paths, (const char *)event.data.scalar.value, PATH_MAX); + FARF(ALWAYS, "dsp_lib_paths is %s", dsp_lib_paths); + found_dsp_path = 1; + done = 1; + } + } + break; + } + case YAML_MAPPING_END_EVENT: + if (in_target_machine) { + // Exiting the target machine mapping + in_target_machine = 0; + if (found_dsp_path) { + done = 1; + } + } + break; + case YAML_STREAM_END_EVENT: + done = 1; + break; + default: + break; + } + + yaml_event_delete(&event); + } + + yaml_parser_delete(&parser); + fclose(file); + + if (!found_dsp_path) { + FARF(ALWAYS, "Warning: DSP_LIBRARY_PATH not found for machine [%s] in configuration file %s\n", + machine_name, filepath); + } +} + +static void parse_config_dir(char *machine_name) { + DIR *dir = opendir(CONFIG_DIR); + struct dirent *entry; + char *file_list[1024]; + int file_count = 0; + char dsp_lib_paths[PATH_MAX] = {0}; + + if (!dir) + return; + + while ((entry = readdir(dir)) != NULL) { + if (entry->d_type == DT_REG && + (strstr(entry->d_name, ".yaml") || strstr(entry->d_name, ".yml"))) { + file_list[file_count] = strdup(entry->d_name); + file_count++; + } + } + closedir(dir); + + qsort(file_list, file_count, sizeof(char *), compare_strings); + + for (int i = 0; i < file_count; i++) { + char filepath[PATH_MAX]; + snprintf(filepath, sizeof(filepath), "%s%s", CONFIG_DIR, file_list[i]); + get_dsp_lib_path(machine_name, filepath, dsp_lib_paths); + free(file_list[i]); + } + + if (dsp_lib_paths[0] != '\0') { + strlcpy(DSP_LIBS_LOCATION, CONFIG_BASE_DIR, sizeof(DSP_LIBS_LOCATION)); + //append slash in case user passed config base dir doesn't end with slash '/' + strlcat(DSP_LIBS_LOCATION, "/", sizeof(DSP_LIBS_LOCATION)); + strlcat(DSP_LIBS_LOCATION, dsp_lib_paths, sizeof(DSP_LIBS_LOCATION)); + strlcat(DSP_LIBS_LOCATION, DEFAULT_DSP_SEARCH_PATHS, sizeof(DSP_LIBS_LOCATION)); + } else { + FARF(ALWAYS, "Warning: No DSP library path found for machine [%s] in any configuration file\n", + machine_name); + } +} + +void configure_dsp_paths() { + char machine_name[PATH_MAX] = {0}; + FILE *file = fopen(MACHINE_NAME_PATH, "r"); + + if (file) { + if (fgets(machine_name, sizeof(machine_name), file) != NULL) + // Remove trailing newline if present + machine_name[strcspn(machine_name, "\n")] = '\0'; + + fclose(file); + parse_config_dir(machine_name); + } else { + char *env_value = getenv("MACHINE_NAME"); + // fallback to look for MACHINE_NAME in environment variable + if (env_value) { + snprintf(machine_name, sizeof(machine_name), "%s", env_value); + machine_name[strcspn(machine_name, "\n")] = '\0'; + parse_config_dir(machine_name); + } + } +} diff --git a/src/fastrpc_ioctl.c b/src/fastrpc_ioctl.c index e0329e1..15c778d 100644 --- a/src/fastrpc_ioctl.c +++ b/src/fastrpc_ioctl.c @@ -5,54 +5,11 @@ #include "AEEStdErr.h" #include "HAP_farf.h" -#include "fastrpc_async.h" #include "fastrpc_internal.h" #include "fastrpc_notif.h" #include "remote.h" #include -/* check async support */ -int is_async_fastrpc_supported(void) { - /* async not supported by upstream driver */ - return 0; -} - -/* Returns the name of the domain based on the following - ADSP/SLPI/MDSP/CDSP - Return Secure node - */ -const char *get_secure_domain_name(int domain_id) { - const char *name; - int domain = GET_DOMAIN_FROM_EFFEC_DOMAIN_ID(domain_id); - - switch (domain) { - case ADSP_DOMAIN_ID: - name = ADSPRPC_SECURE_DEVICE; - break; - case SDSP_DOMAIN_ID: - name = SDSPRPC_SECURE_DEVICE; - break; - case MDSP_DOMAIN_ID: - name = MDSPRPC_SECURE_DEVICE; - break; - case CDSP_DOMAIN_ID: - name = CDSPRPC_SECURE_DEVICE; - break; - case CDSP1_DOMAIN_ID: - name = CDSP1RPC_SECURE_DEVICE; - break; - case GDSP0_DOMAIN_ID: - name = GDSP0RPC_SECURE_DEVICE; - break; - case GDSP1_DOMAIN_ID: - name = GDSP1RPC_SECURE_DEVICE; - break; - default: - name = DEFAULT_DEVICE; - break; - } - return name; -} - int ioctl_init(int dev, uint32_t flags, int attr, unsigned char *shell, int shelllen, int shellfd, char *mem, int memlen, int memfd, int tessiglen) { int ioErr = 0; @@ -91,7 +48,7 @@ int ioctl_init(int dev, uint32_t flags, int attr, unsigned char *shell, int shel } int ioctl_invoke(int dev, int req, remote_handle handle, uint32_t sc, void *pra, - int *fds, unsigned int *attrs, void *job, unsigned int *crc, + int *fds, unsigned int *attrs, unsigned int *crc, uint64_t *perf_kernel, uint64_t *perf_dsp) { int ioErr = AEE_SUCCESS; struct fastrpc_ioctl_invoke invoke = {0}; @@ -107,12 +64,6 @@ int ioctl_invoke(int dev, int req, remote_handle handle, uint32_t sc, void *pra, return ioErr; } -int ioctl_invoke2_response(int dev, fastrpc_async_jobid *jobid, - remote_handle *handle, uint32_t *sc, int *result, - uint64_t *perf_kernel, uint64_t *perf_dsp) { - return AEE_EUNSUPPORTED; -} - int ioctl_invoke2_notif(int dev, int *domain, int *session, int *status) { return AEE_EUNSUPPORTED; } @@ -256,4 +207,13 @@ int ioctl_mdctx_manage(int dev, int req, void *user_ctx, { // TODO: Implement this for opensource return AEE_EUNSUPPORTED; -} \ No newline at end of file +} + +int fastrpc_async_get_status(fastrpc_async_jobid jobid, int timeout_us, + int *result) { + return AEE_EUNSUPPORTED; +} + +int fastrpc_release_async_job(fastrpc_async_jobid jobid) { + return AEE_EUNSUPPORTED; +} diff --git a/src/fastrpc_latency.c b/src/fastrpc_latency.c deleted file mode 100644 index 46fdab8..0000000 --- a/src/fastrpc_latency.c +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef FARF_ERROR -#define FARF_ERROR 1 -#endif - -#include "AEEStdErr.h" -#include "AEEstd.h" -#include "HAP_farf.h" -#include "fastrpc_common.h" -#include "fastrpc_internal.h" -#include "fastrpc_latency.h" -#include "verify.h" - -int fastrpc_latency_invoke_incr(struct fastrpc_latency *qp) { - if (qp == NULL || qp->state == FASTRPC_LATENCY_STOP) - goto bail; - qp->invoke++; - if (qp->vote == FASTRPC_LATENCY_VOTE_OFF) { - pthread_mutex_lock(&qp->wmut); - pthread_cond_signal(&qp->cond); - pthread_mutex_unlock(&qp->wmut); - } -bail: - return 0; -} - -int fastrpc_latency_init(int dev, struct fastrpc_latency *qos) { - int nErr = 0; - - VERIFYC(qos && dev != -1, AEE_ERPC); - - qos->dev = dev; - qos->state = FASTRPC_LATENCY_STOP; - qos->thread = 0; - qos->wait_time = FASTRPC_LATENCY_WAIT_TIME_USEC; - pthread_mutex_init(&qos->mut, 0); - pthread_mutex_init(&qos->wmut, 0); - pthread_cond_init(&qos->cond, NULL); -bail: - return nErr; -} - -int fastrpc_latency_deinit(struct fastrpc_latency *qos) { - int nErr = 0; - - VERIFYC(qos, AEE_ERPC); - if (qos->state == FASTRPC_LATENCY_START) { - pthread_mutex_lock(&qos->wmut); - qos->exit = FASTRPC_LATENCY_EXIT; - pthread_cond_signal(&qos->cond); - pthread_mutex_unlock(&qos->wmut); - if (qos->thread) { - pthread_join(qos->thread, 0); - qos->thread = 0; - FARF(ALWAYS, "latency thread joined"); - } - pthread_mutex_destroy(&qos->mut); - pthread_mutex_destroy(&qos->wmut); - } -bail: - return nErr; -} - -/* FastRPC QoS handler votes for pm_qos latency based on - * RPC activity in a window of time. - */ -static void *fastrpc_latency_thread_handler(void *arg) { - int nErr = 0; - long ns = 0; - struct timespec tw; - struct timeval tp; - int invoke = 0; - struct fastrpc_ioctl_control qos = {0}; - struct fastrpc_ctrl_latency lp = {0}; - struct fastrpc_latency *qp = (struct fastrpc_latency *)arg; - - if (qp == NULL) { - nErr = AEE_ERPC; - FARF(ERROR, "Error 0x%x: %s failed \n", nErr, __func__); - return NULL; - } - VERIFYC(qp->dev != -1, AEE_ERPC); - - FARF(ALWAYS, "%s started for QoS with activity window %d ms", __func__, - FASTRPC_LATENCY_WAIT_TIME_USEC / MS_TO_US); - - // Look for RPC activity in 100 ms window - qp->wait_time = FASTRPC_LATENCY_WAIT_TIME_USEC; - qp->invoke++; - while (1) { - nErr = gettimeofday(&tp, NULL); - /* valid values for "tv_nsec" are [0, 999999999] */ - ns = ((tp.tv_usec + qp->wait_time) * US_TO_NS); - tw.tv_sec = tp.tv_sec + (ns / SEC_TO_NS); - tw.tv_nsec = (ns % SEC_TO_NS); - - pthread_mutex_lock(&qp->wmut); - if (qp->wait_time) - pthread_cond_timedwait(&qp->cond, &qp->wmut, &tw); - else - pthread_cond_wait(&qp->cond, &qp->wmut); - pthread_mutex_unlock(&qp->wmut); - - if (qp->exit == FASTRPC_LATENCY_EXIT) { - qp->exit = 0; - break; - } - - pthread_mutex_lock(&qp->mut); - invoke = qp->invoke; - qp->invoke = 0; - pthread_mutex_unlock(&qp->mut); - - if (invoke) { - // found RPC activity in window. vote for pm_qos. - qp->wait_time = FASTRPC_LATENCY_WAIT_TIME_USEC; - if (qp->vote == FASTRPC_LATENCY_VOTE_OFF) { - lp.enable = FASTRPC_LATENCY_VOTE_ON; - lp.latency = qp->latency; - nErr = ioctl_control(qp->dev, DSPRPC_CONTROL_LATENCY, &lp); - if (nErr == AEE_SUCCESS) { - qp->vote = FASTRPC_LATENCY_VOTE_ON; - } else if (nErr == AEE_EUNSUPPORTED) { - goto bail; - } else { - FARF(ERROR, - "Error %d: %s: PM QoS ON request failed with errno %d (%s)", - nErr, __func__, errno, strerror(errno)); - } - } - } else { - // No RPC activity detected in a window. Remove pm_qos vote. - qp->wait_time = 0; - if (qp->vote == FASTRPC_LATENCY_VOTE_ON) { - lp.enable = FASTRPC_LATENCY_VOTE_OFF; - lp.latency = 0; - nErr = ioctl_control(qp->dev, DSPRPC_CONTROL_LATENCY, &lp); - if (nErr == AEE_SUCCESS) { - qp->vote = FASTRPC_LATENCY_VOTE_OFF; - } else if (nErr == AEE_EUNSUPPORTED) { - goto bail; - } else { - FARF(ERROR, - "Error %d: %s: PM QoS OFF request failed with errno %d (%s)", - nErr, __func__, errno, strerror(errno)); - } - } - } - } - FARF(ALWAYS, "FastRPC latency thread for QoS exited"); -bail: - if (nErr != AEE_SUCCESS) { - FARF(ERROR, - "Error 0x%x: %s failed for wait time %d latency control enable %d " - "latency %d\n", - nErr, __func__, qp->wait_time, qos.lp.enable, qos.lp.latency); - } - return NULL; -} - -int fastrpc_set_pm_qos(struct fastrpc_latency *qos, uint32_t enable, - uint32_t latency) { - int nErr = AEE_SUCCESS; - int state = 0; - - VERIFYC(qos != NULL, AEE_EBADPARM); - if (qos->exit == FASTRPC_LATENCY_EXIT) - goto bail; - pthread_mutex_lock(&qos->mut); - state = qos->state; - qos->latency = latency; - pthread_mutex_unlock(&qos->mut); - - if (!enable && state == FASTRPC_LATENCY_START) { - qos->exit = FASTRPC_LATENCY_EXIT; - pthread_mutex_lock(&qos->wmut); - pthread_cond_signal(&qos->cond); - pthread_mutex_unlock(&qos->wmut); - } - - if (enable && state == FASTRPC_LATENCY_STOP) { - qos->state = FASTRPC_LATENCY_START; - VERIFY(AEE_SUCCESS == (nErr = pthread_create(&qos->thread, 0, - fastrpc_latency_thread_handler, - (void *)qos))); - } -bail: - return nErr; -} diff --git a/src/fastrpc_mem.c b/src/fastrpc_mem.c index 8f62fc2..bdab811 100644 --- a/src/fastrpc_mem.c +++ b/src/fastrpc_mem.c @@ -110,6 +110,18 @@ struct static_map_list { pthread_mutex_t mut; }; +struct fastrpc_remote_map { + QNode qn; + uint64_t vadsp; + uint32_t flags; +}; + +struct fastrpc_remote_map_list { + QList ql; + pthread_mutex_t mut; +}; + +static struct fastrpc_remote_map_list memlist[NUM_DOMAINS_EXTEND]; static struct static_map_list smaplst[NUM_DOMAINS_EXTEND]; static struct mem_to_fd_list fdlist; static struct dma_handle_info dhandles[MAX_DMA_HANDLES]; @@ -128,6 +140,8 @@ int fastrpc_mem_init(void) { FOR_EACH_EFFECTIVE_DOMAIN_ID(ii) { QList_Ctor(&smaplst[ii].ql); pthread_mutex_init(&smaplst[ii].mut, 0); + QList_Ctor(&memlist[ii].ql); + pthread_mutex_init(&memlist[ii].mut, 0); } return 0; } @@ -138,10 +152,35 @@ int fastrpc_mem_deinit(void) { pthread_mutex_destroy(&fdlist.mut); FOR_EACH_EFFECTIVE_DOMAIN_ID(ii) { pthread_mutex_destroy(&smaplst[ii].mut); + pthread_mutex_destroy(&memlist[ii].mut); } return 0; } +static int fastrpc_remote_map_lookup(int domain, uint64_t vadsp, uint32_t *flags_out, struct fastrpc_remote_map **out) +{ + QNode *pn, *pnn; + struct fastrpc_remote_map *mNode; + + if (!flags_out || !out) + return AEE_EBADPARM; + + *out = NULL; + pthread_mutex_lock(&memlist[domain].mut); + QLIST_NEXTSAFE_FOR_ALL(&memlist[domain].ql, pn, pnn) { + mNode = STD_RECOVER_REC(struct fastrpc_remote_map, qn, pn); + if (mNode->vadsp == vadsp) { + *flags_out = mNode->flags; + *out = mNode; + QNode_DequeueZ(&mNode->qn); + pthread_mutex_unlock(&memlist[domain].mut); + return AEE_SUCCESS; + } + } + pthread_mutex_unlock(&memlist[domain].mut); + return AEE_ERESOURCENOTFOUND; +} + static void *remote_register_fd_attr(int fd, size_t size, int attr) { int nErr = AEE_SUCCESS; void *po = NULL; @@ -440,51 +479,37 @@ int fdlist_fd_from_buf(void *buf, int bufLen, int *nova, void **base, int *attr, return 0; } -int fastrpc_mmap(int domain, int fd, void *vaddr, int offset, size_t length, - enum fastrpc_map_flags flags) { +/** + * Helper function to perform complete mmap operation including error handling + * Returns 0 on success, error code on failure + * On success, vaddrout contains the DSP virtual address + */ +static int fastrpc_mmap_helper(int *domain, int fd, void *vaddr, int offset, + size_t length, uint32_t flags, int attrs, + uint64_t *vaddrout) { struct fastrpc_map map = {0}; - int nErr = 0, dev = -1, iocErr = 0, attrs = 0, ref = 0; - uint64_t vaddrout = 0; + int nErr = 0, dev = -1, iocErr = 0, ref = 0; struct static_map *mNode = NULL, *tNode = NULL; QNode *pn, *pnn; - VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once())); - - FARF(RUNTIME_RPC_HIGH, - "%s: domain %d fd %d addr %p length 0x%zx flags 0x%x offset 0x%x", - __func__, domain, fd, vaddr, length, flags, offset); - - /** - * Mask is applied on "flags" parameter to extract map control flags - * and SMMU mapping control attributes. Currently no attributes are - * suppported. It allows future extension of the fastrpc_mmap API - * for SMMU mapping control attributes. - */ - attrs = flags & (~FASTRPC_MAP_FLAGS_MASK); - flags = flags & FASTRPC_MAP_FLAGS_MASK; - VERIFYC(fd >= 0 && offset == 0 && attrs == 0, AEE_EBADPARM); - VERIFYC(flags >= 0 && flags < FASTRPC_MAP_MAX && - flags != FASTRPC_MAP_RESERVED, - AEE_EBADPARM); - // Get domain and open session if not already open - if (domain == -1) { - domain = get_current_domain(); + if (*domain == -1) { + *domain = get_current_domain(); } - VERIFYC(IS_VALID_EFFECTIVE_DOMAIN_ID(domain), AEE_EBADPARM); - FASTRPC_GET_REF(domain); - VERIFY(AEE_SUCCESS == (nErr = fastrpc_session_dev(domain, &dev))); + VERIFYC(IS_VALID_EFFECTIVE_DOMAIN_ID(*domain), AEE_EBADPARM); + FASTRPC_GET_REF(*domain); + VERIFY(AEE_SUCCESS == (nErr = fastrpc_session_dev(*domain, &dev))); VERIFYC(-1 != dev, AEE_ERPC); /* Search for mapping in current session static map list */ - pthread_mutex_lock(&smaplst[domain].mut); - QLIST_NEXTSAFE_FOR_ALL(&smaplst[domain].ql, pn, pnn) { + pthread_mutex_lock(&smaplst[*domain].mut); + QLIST_NEXTSAFE_FOR_ALL(&smaplst[*domain].ql, pn, pnn) { tNode = STD_RECOVER_REC(struct static_map, qn, pn); if (tNode->map.fd == fd) { break; } } - pthread_mutex_unlock(&smaplst[domain].mut); + pthread_mutex_unlock(&smaplst[*domain].mut); // Raise error if map found already if (tNode) { @@ -505,13 +530,13 @@ int fastrpc_mmap(int domain, int fd, void *vaddr, int offset, size_t length, map.m.vaddrout = 0; mNode->map = map.m; iocErr = ioctl_mmap(dev, MEM_MAP, flags, attrs, fd, offset, length, - (uint64_t)vaddr, &vaddrout); + (uint64_t)vaddr, vaddrout); if (!iocErr) { - mNode->map.vaddrout = vaddrout; + mNode->map.vaddrout = *vaddrout; mNode->refs = 1; - pthread_mutex_lock(&smaplst[domain].mut); - QList_AppendNode(&smaplst[domain].ql, &mNode->qn); - pthread_mutex_unlock(&smaplst[domain].mut); + pthread_mutex_lock(&smaplst[*domain].mut); + QList_AppendNode(&smaplst[*domain].ql, &mNode->qn); + pthread_mutex_unlock(&smaplst[*domain].mut); mNode = NULL; } else if (errno == ENOTTY || iocErr == (int)(DSP_AEE_EOFFSET | AEE_EUNSUPPORTED)) { @@ -521,16 +546,17 @@ int fastrpc_mmap(int domain, int fd, void *vaddr, int offset, size_t length, nErr = AEE_EFAILED; goto bail; } + bail: - FASTRPC_PUT_REF(domain); + FASTRPC_PUT_REF(*domain); if (nErr) { if (iocErr == 0) { errno = 0; } FARF(ERROR, - "Error 0x%x: %s failed to map buffer fd %d, addr %p, length 0x%zx, " + "Error 0x%x: %s failed for fd %d, addr %p, length 0x%zx, " "domain %d, flags 0x%x, ioctl ret 0x%x, errno %s", - nErr, __func__, fd, vaddr, length, domain, flags, iocErr, + nErr, __func__, fd, vaddr, length, *domain, flags, iocErr, strerror(errno)); } if (mNode) { @@ -540,6 +566,41 @@ int fastrpc_mmap(int domain, int fd, void *vaddr, int offset, size_t length, return nErr; } +int fastrpc_mmap(int domain, int fd, void *vaddr, int offset, size_t length, + enum fastrpc_map_flags flags) { + int nErr = 0, attrs = 0; + uint64_t vaddrout = 0; + + VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once())); + + FARF(RUNTIME_RPC_HIGH, + "%s: domain %d fd %d addr %p length 0x%zx flags 0x%x offset 0x%x", + __func__, domain, fd, vaddr, length, flags, offset); + + /** + * Mask is applied on "flags" parameter to extract map control flags + * and SMMU mapping control attributes. Currently no attributes are + * suppported. It allows future extension of the fastrpc_mmap API + * for SMMU mapping control attributes. + */ + attrs = flags & (~FASTRPC_MAP_FLAGS_MASK); + flags = flags & FASTRPC_MAP_FLAGS_MASK; + VERIFYC(fd >= 0 && offset == 0 && attrs == 0, AEE_EBADPARM); + VERIFYC(flags >= 0 && flags < FASTRPC_MAP_MAX && + flags != FASTRPC_MAP_RESERVED, + AEE_EBADPARM); + + nErr = fastrpc_mmap_helper(&domain, fd, vaddr, offset, length, flags, attrs, + &vaddrout); + +bail: + if (nErr) { + FARF(ERROR, "Error 0x%x: %s failed for fd %d, addr %p, length 0x%zx, domain %d, flags 0x%x", + nErr, __func__, fd, vaddr, length, domain, flags); + } + return nErr; +} + int fastrpc_munmap(int domain, int fd, void *vaddr, size_t length) { int nErr = 0, dev = -1, iocErr = 0, locked = 0, ref = 0; struct static_map *mNode = NULL; @@ -614,6 +675,104 @@ int fastrpc_munmap(int domain, int fd, void *vaddr, size_t length) { return nErr; } +int fastrpc_mmap_internal(int domain, int fd, void *vaddr, int offset, + size_t length, uint32_t flags, uint64_t *raddr) { + int nErr = 0, attrs = 0; + + VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once())); + + VERIFYC(raddr != NULL, AEE_EBADPARM); + + FARF(RUNTIME_RPC_HIGH, + "%s: domain %d fd %d addr %p length 0x%zx flags 0x%x offset 0x%x", + __func__, domain, fd, vaddr, length, flags, offset); + + attrs = flags & (~FASTRPC_MAP_FLAGS_MASK); + flags = flags & FASTRPC_MAP_FLAGS_MASK; + VERIFYC(fd >= 0 && offset == 0 && attrs == 0, AEE_EBADPARM); + + nErr = fastrpc_mmap_helper(&domain, fd, vaddr, offset, length, flags, attrs, + raddr); + +bail: + if (nErr) { + FARF(ERROR, "Error 0x%x: %s failed for fd %d, addr %p, length 0x%zx, domain %d, flags 0x%x", + nErr, __func__, fd, vaddr, length, domain, flags); + } + return nErr; +} + +int fastrpc_munmap_internal(int domain, uint64_t raddr, size_t length) { + int nErr = 0, dev = -1, iocErr = 0, locked = 0, ref = 0; + struct static_map *mNode = NULL; + QNode *pn, *pnn; + + VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once())); + + FARF(RUNTIME_RPC_HIGH, "%s: domain %d raddr 0x%llx length 0x%zx", __func__, + domain, raddr, length); + if (domain == -1) { + domain = get_current_domain(); + } + VERIFYC(IS_VALID_EFFECTIVE_DOMAIN_ID(domain), AEE_EBADPARM); + FASTRPC_GET_REF(domain); + VERIFY(AEE_SUCCESS == (nErr = fastrpc_session_dev(domain, &dev))); + /** + * Search for mapping in current static map list using DSP virtual address (raddr). + */ + pthread_mutex_lock(&smaplst[domain].mut); + locked = 1; + QLIST_NEXTSAFE_FOR_ALL(&smaplst[domain].ql, pn, pnn) { + mNode = STD_RECOVER_REC(struct static_map, qn, pn); + if (mNode->map.vaddrout == raddr) { + FARF(RUNTIME_RPC_HIGH, "%s: unmap found for raddr 0x%llx domain %d", __func__, + raddr, domain); + break; + } + } + VERIFYC(mNode && mNode->map.vaddrout == raddr, AEE_ENOSUCHMAP); + if (mNode->refs > 1) { + FARF(ERROR, "%s: Attempt to unmap raddr 0x%llx with %d outstanding references", + __func__, raddr, mNode->refs - 1); + nErr = AEE_EBADPARM; + goto bail; + } + mNode->refs = 0; + locked = 0; + pthread_mutex_unlock(&smaplst[domain].mut); + + iocErr = ioctl_munmap(dev, MEM_UNMAP, 0, 0, mNode->map.fd, mNode->map.length, + mNode->map.vaddrout); + pthread_mutex_lock(&smaplst[domain].mut); + locked = 1; + if (iocErr == 0) { + QNode_DequeueZ(&mNode->qn); + free(mNode); + mNode = NULL; + } else if (errno == ENOTTY || errno == EINVAL) { + nErr = AEE_EUNSUPPORTED; + } else { + mNode->refs = 1; + nErr = AEE_EFAILED; + } +bail: + if (locked == 1) { + locked = 0; + pthread_mutex_unlock(&smaplst[domain].mut); + } + FASTRPC_PUT_REF(domain); + if (nErr) { + if (iocErr == 0) { + errno = 0; + } + FARF(ERROR, + "Error 0x%x: %s failed raddr 0x%llx, length 0x%zx, domain %d, " + "ioctl ret 0x%x, errno %s", + nErr, __func__, raddr, length, domain, iocErr, strerror(errno)); + } + return nErr; +} + int remote_mem_map(int domain, int fd, int flags, uint64_t vaddr, size_t size, uint64_t *raddr) { int nErr = 0; @@ -623,8 +782,8 @@ int remote_mem_map(int domain, int fd, int flags, uint64_t vaddr, size_t size, VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once())); FARF(RUNTIME_RPC_HIGH, - "%s: domain %d fd %d addr 0x%llx size 0x%zx flags 0x%x", __func__, - domain, fd, vaddr, size, flags); + "%s: domain %d fd %d addr 0x%" PRIx64 " size 0x%zx flags 0x%x", + __func__, domain, fd, vaddr, size, flags); VERIFYC(fd >= 0, AEE_EBADPARM); VERIFYC(size >= 0, AEE_EBADPARM); @@ -646,8 +805,8 @@ int remote_mem_map(int domain, int fd, int flags, uint64_t vaddr, size_t size, nErr = convert_kernel_to_user_error(nErr, errno); if (0 == check_rpc_error(nErr)) { FARF(ERROR, - "Error 0x%x: %s failed to map buffer fd %d addr 0x%llx size 0x%zx " - "domain %d flags %d errno %s", + "Error 0x%x: %s failed to map buffer fd %d addr 0x%" PRIx64 + " size 0x%zx domain %d flags %d errno %s", nErr, __func__, fd, vaddr, size, domain, flags, strerror(errno)); } } @@ -661,8 +820,8 @@ int remote_mem_unmap(int domain, uint64_t raddr, size_t size) { VERIFYC(size >= 0, AEE_EBADPARM); VERIFYC(raddr != 0, AEE_EBADPARM); - FARF(RUNTIME_RPC_HIGH, "%s: domain %d addr 0x%llx size 0x%zx", __func__, - domain, raddr, size); + FARF(RUNTIME_RPC_HIGH, "%s: domain %d addr 0x%" PRIx64 " size 0x%zx", + __func__, domain, raddr, size); if (domain == -1) { domain = get_current_domain(); } @@ -678,8 +837,8 @@ int remote_mem_unmap(int domain, uint64_t raddr, size_t size) { nErr = convert_kernel_to_user_error(nErr, errno); if (0 == check_rpc_error(nErr)) { FARF(ERROR, - "Error 0x%x: %s failed to unmap buffer addr 0x%llx size 0x%zx " - "domain %d errno %s", + "Error 0x%x: %s failed to unmap buffer addr 0x%" PRIx64 + " size 0x%zx domain %d errno %s", nErr, __func__, raddr, size, domain, strerror(errno)); } } @@ -698,15 +857,29 @@ int remote_mmap64_internal(int fd, uint32_t flags, uint64_t vaddrin, FASTRPC_GET_REF(domain); VERIFY(AEE_SUCCESS == (nErr = fastrpc_session_dev(domain, &dev))); VERIFYM(-1 != dev, AEE_ERPC, "Invalid device\n"); - nErr = ioctl_mmap(dev, MMAP_64, flags, 0, fd, 0, size, vaddrin, &vaout); + if (flags == ADSP_MMAP_ADD_PAGES || flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + nErr = ioctl_mmap(dev, MMAP_64, flags, 0, fd, 0, size, vaddrin, &vaout); + } else { + VERIFY(AEE_SUCCESS == + (nErr = fastrpc_mmap_internal(domain, fd, (void *)(uintptr_t)vaddrin, 0, size, + flags, &vaout))); + } *vaddrout = vaout; + pthread_mutex_lock(&memlist[domain].mut); + struct fastrpc_remote_map *mNode = malloc(sizeof(*mNode)); + if (mNode) { + mNode->vadsp = vaout; + mNode->flags = flags; + QList_AppendNode(&memlist[domain].ql, &mNode->qn); + } + pthread_mutex_unlock(&memlist[domain].mut); bail: FASTRPC_PUT_REF(domain); if (nErr != AEE_SUCCESS) { nErr = convert_kernel_to_user_error(nErr, errno); FARF(ERROR, - "Error 0x%x: %s failed for fd 0x%x of size %lld (flags 0x%x, vaddrin " - "0x%llx) errno %s\n", + "Error 0x%x: %s failed for fd 0x%x of size %" PRId64 " (flags 0x%x, " + "vaddrin 0x%" PRIx64 ") errno %s\n", nErr, __func__, fd, size, flags, vaddrin, strerror(errno)); } return nErr; @@ -732,8 +905,8 @@ int remote_mmap64(int fd, uint32_t flags, uint64_t vaddrin, int64_t size, bail: if ((nErr != AEE_SUCCESS) && (log == 1)) { FARF(ERROR, - "Error 0x%x: %s failed for fd 0x%x of size %lld (flags 0x%x, vaddrin " - "0x%llx)\n", + "Error 0x%x: %s failed for fd 0x%x of size %" PRId64 " (flags 0x%x, " + "vaddrin 0x%" PRIx64 ")\n", nErr, __func__, fd, size, flags, vaddrin); } return nErr; @@ -754,6 +927,8 @@ int remote_mmap(int fd, uint32_t flags, uint32_t vaddrin, int size, int remote_munmap64(uint64_t vaddrout, int64_t size) { int dev, domain = DEFAULT_DOMAIN_ID, nErr = AEE_SUCCESS, ref = 0; + uint32_t rflags; + struct fastrpc_remote_map *mNode = NULL; VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once())); @@ -763,14 +938,30 @@ int remote_munmap64(uint64_t vaddrout, int64_t size) { /* Don't open session in unmap. Return success if device already closed */ FASTRPC_GET_REF(domain); VERIFY(AEE_SUCCESS == (nErr = fastrpc_session_dev(domain, &dev))); - nErr = ioctl_munmap(dev, MUNMAP_64, 0, 0, -1, size, vaddrout); + + if (AEE_SUCCESS == fastrpc_remote_map_lookup(domain, vaddrout, &rflags, &mNode)) { + if (rflags == ADSP_MMAP_ADD_PAGES || rflags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + nErr = ioctl_munmap(dev, MUNMAP_64, 0, 0, -1, size, vaddrout); + } else { + nErr = fastrpc_munmap_internal(domain, (uint64_t)vaddrout, size); + } + if (nErr == AEE_SUCCESS) { + free(mNode); + } else { + pthread_mutex_lock(&memlist[domain].mut); + QList_AppendNode(&memlist[domain].ql, &mNode->qn); + pthread_mutex_unlock(&memlist[domain].mut); + } + } else { + nErr = ioctl_munmap(dev, MUNMAP_64, 0, 0, -1, size, vaddrout); + } bail: FASTRPC_PUT_REF(domain); if (nErr != AEE_SUCCESS) { nErr = convert_kernel_to_user_error(nErr, errno); FARF(ERROR, - "Error 0x%x: %s failed for size %lld (vaddrout 0x%llx) errno %s\n", - nErr, __func__, size, vaddrout, strerror(errno)); + "Error 0x%x: %s failed for size %" PRId64 " (vaddrout 0x%" PRIx64 ") " + "errno %s\n", nErr, __func__, size, vaddrout, strerror(errno)); } return nErr; } diff --git a/src/listener_android.c b/src/listener_android.c index 712945c..171329d 100644 --- a/src/listener_android.c +++ b/src/listener_android.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "AEEStdErr.h" #include "AEEstd.h" @@ -132,8 +133,8 @@ static void listener(listener_config *me) { memset(args, 0, sizeof(args)); if (eheap || eflags || emin) { FARF(RUNTIME_RPC_HIGH, - "listener using ion heap: %d flags: %x cache: %lld\n", (int)heapid, - (int)flags, cache_size); + "listener using ion heap: %d flags: %x cache: %" PRId64 "\n", + (int)heapid, (int)flags, cache_size); } do { @@ -349,8 +350,9 @@ static void *listener_start_thread(void *arg) { nErr = __QAIC_HEADER(adsp_listener1_init2)(adsp_listener1_handle); if ((nErr == DSP_AEE_EOFFSET + AEE_ERPC) || nErr == DSP_AEE_EOFFSET + AEE_ENOSUCHMOD) { - FARF(ERROR, "Error 0x%x: %s domains support not available in listener", - nErr, __func__); + FARF(ALWAYS, + "Warning: %s domain support is unavailable on DSP in listener", + __func__); fastrpc_update_module_list(DOMAIN_LIST_DEQUEUE, domain, _const_adsp_listener1_handle, NULL, NULL); adsp_listener1_handle = INVALID_HANDLE; VERIFY(AEE_SUCCESS == (nErr = __QAIC_HEADER(adsp_listener_init2)())); diff --git a/src/mod_table.c b/src/mod_table.c index d19fa90..d88468c 100644 --- a/src/mod_table.c +++ b/src/mod_table.c @@ -549,7 +549,9 @@ static int open_mod_table_open_dynamic(struct open_mod_table *me, break; } } - rv = snprintf(tmp, tmplen, "%s_system.so", tmp); + /* Append "_system.so" to base name (avoid overlapping buffers in snprintf) */ + strlcat(tmp, "_system.so", tmplen); + rv = strlen(tmp); VERIFYC((rv > 0) && (tmplen >= rv), AEE_EBADPARM); FARF(RUNTIME_RPC_HIGH, "calling dlopen for %s", tmp); dm->dlhandle = DLOPEN(tmp, RTLD_NOW); diff --git a/src/rpcmem_linux.c b/src/rpcmem_linux.c index a0814b9..8a9ce40 100644 --- a/src/rpcmem_linux.c +++ b/src/rpcmem_linux.c @@ -118,12 +118,6 @@ void rpcmem_deinit() { pthread_mutex_destroy(&rpcmt); } -int rpcmem_set_dmabuf_name(const char *name, int fd, int heapid, - void *buf, uint32_t rpcflags) { - // Dummy call where DMABUF is not used - return 0; -} - int rpcmem_to_fd_internal(void *po) { struct rpc_info *rinfo, *rfree = 0; QNode *pn, *pnn; @@ -246,6 +240,10 @@ void *rpcmem_alloc(int heapid, uint32_t flags, int size) { return rpcmem_alloc_internal(heapid, flags, size); } +void *rpcmem_alloc2(int heapid, uint32_t flags, size_t size) { + return rpcmem_alloc_internal(heapid, flags, (size_t)size); +} + void rpcmem_deinit_internal() { rpcmem_deinit(); } void rpcmem_init_internal() { rpcmem_init(); } diff --git a/src/symbols.lst b/src/symbols.lst index 05f6adb..66ecb7d 100644 --- a/src/symbols.lst +++ b/src/symbols.lst @@ -34,8 +34,6 @@ rpcmem_alloc2; rpcmem_free; rpcmem_to_fd; - remote_handle_invoke_async; - remote_handle64_invoke_async; fastrpc_async_get_status; fastrpc_release_async_job; dspqueue_create;