Add 'qcom/opensource/wlan/platform/' from commit '54afb87accfa6775cef4e9adcd4e6f08c64a5fb1'
git-subtree-dir: qcom/opensource/wlan/platform git-subtree-mainline:c74a556fc1
git-subtree-split:54afb87acc
Change-Id: repo: https://git.codelinaro.org/clo/la/platform/vendor/qcom-opensource/wlan/platform tag: LA.VENDOR.14.3.0.r1-17300-lanai.QSSI15.0
这个提交包含在:
@@ -0,0 +1,135 @@
|
||||
# Android Makefile for WLAN platform modules
|
||||
|
||||
ENABLE_WLAN_PLATFORM_DLKM := false
|
||||
ifeq ($(TARGET_KERNEL_DLKM_DISABLE), true)
|
||||
ifeq ($(TARGET_KERNEL_DLKM_WLAN_OVERRIDE), true)
|
||||
ENABLE_WLAN_PLATFORM_DLKM := true
|
||||
endif
|
||||
else
|
||||
ENABLE_WLAN_PLATFORM_DLKM := true
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_WLAN_PLATFORM_DLKM), true)
|
||||
|
||||
# LOCAL_PATH is a relative path to root build directory.
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
LOCAL_MODULE_DDK_BUILD := true
|
||||
LOCAL_MODULE_DDK_ALLOW_UNSAFE_HEADERS := true
|
||||
LOCAL_MODULE_KO_DIRS := cnss2/cnss2.ko
|
||||
LOCAL_MODULE_KO_DIRS += cnss_utils/cnss_plat_ipc_qmi_svc.ko
|
||||
LOCAL_MODULE_KO_DIRS += cnss_utils/wlan_firmware_service.ko
|
||||
LOCAL_MODULE_KO_DIRS += cnss_genl/cnss_nl.ko
|
||||
LOCAL_MODULE_KO_DIRS += cnss_prealloc/cnss_prealloc.ko
|
||||
LOCAL_MODULE_KO_DIRS += cnss_utils/cnss_utils.ko
|
||||
LOCAL_MODULE_KO_DIRS += icnss2/icnss2.ko
|
||||
|
||||
BOARD_COMMON_DIR ?= device/qcom/common
|
||||
DLKM_DIR := $(TOP)/$(BOARD_COMMON_DIR)/dlkm
|
||||
|
||||
# WLAN_PLATFORM_ROOT needs to be a absolute since it will be used
|
||||
# for header files. $(TOP) cannot be used here since it will be
|
||||
# resolved as "." which won't work for Kbuild.
|
||||
KBUILD_OPTIONS := WLAN_PLATFORM_ROOT=$(abspath $(LOCAL_PATH))
|
||||
|
||||
# WLAN_PLATFORM_KBUILD_OPTIONS should be defined from upper level
|
||||
# Product or Board related Makefiles like wlan.mk.
|
||||
KBUILD_OPTIONS += $(foreach wlan_platform_kbuild_option, \
|
||||
$(WLAN_PLATFORM_KBUILD_OPTIONS), \
|
||||
$(wlan_platform_kbuild_option))
|
||||
|
||||
# Sourcing all files is for better incremental compilation.
|
||||
CNSS_SRC_FILES := \
|
||||
$(wildcard $(LOCAL_PATH)/*) \
|
||||
$(wildcard $(LOCAL_PATH)/*/*) \
|
||||
|
||||
ifeq ($(TARGET_KERNEL_DLKM_SECURE_MSM_OVERRIDE), true)
|
||||
KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS=$(PWD)/$(call intermediates-dir-for,DLKM,sec-module-symvers)/Module.symvers
|
||||
endif
|
||||
|
||||
# Module.symvers needs to be generated as a intermediate module so that
|
||||
# other modules which depend on WLAN platform modules can set local
|
||||
# dependencies to it.
|
||||
|
||||
########################### Module.symvers ############################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(CNSS_SRC_FILES)
|
||||
LOCAL_MODULE := wlan-platform-module-symvers
|
||||
LOCAL_MODULE_STEM := Module.symvers
|
||||
LOCAL_MODULE_KBUILD_NAME := Module.symvers
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
|
||||
# Below are for Android build system to recognize each module name, so
|
||||
# they can be installed properly. Since Kbuild is used to compile these
|
||||
# modules, invoking any of them will cause other modules to be compiled
|
||||
# as well if corresponding flags are added in KBUILD_OPTIONS from upper
|
||||
# level Makefiles like wlan.mk.
|
||||
|
||||
################################ cnss2 ################################
|
||||
include $(CLEAR_VARS)
|
||||
ifeq ($(TARGET_KERNEL_DLKM_SECURE_MSM_OVERRIDE), true)
|
||||
LOCAL_REQUIRED_MODULES := sec-module-symvers
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(call intermediates-dir-for,DLKM,sec-module-symvers)/Module.symvers
|
||||
endif #TARGET_KERNEL_DLKM_SECURE_MSM_OVERRIDE
|
||||
LOCAL_SRC_FILES := $(CNSS_SRC_FILES)
|
||||
LOCAL_MODULE := cnss2.ko
|
||||
LOCAL_MODULE_KBUILD_NAME := cnss2/cnss2.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
######################## cnss_plat_ipc_qmi_svc ########################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(CNSS_SRC_FILES)
|
||||
LOCAL_MODULE := cnss_plat_ipc_qmi_svc.ko
|
||||
LOCAL_MODULE_KBUILD_NAME := cnss_utils/cnss_plat_ipc_qmi_svc.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
######################## wlan_firmware_service ########################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(CNSS_SRC_FILES)
|
||||
LOCAL_MODULE := wlan_firmware_service.ko
|
||||
LOCAL_MODULE_KBUILD_NAME := cnss_utils/wlan_firmware_service.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
############################### cnss_nl ###############################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(CNSS_SRC_FILES)
|
||||
LOCAL_MODULE := cnss_nl.ko
|
||||
LOCAL_MODULE_KBUILD_NAME := cnss_genl/cnss_nl.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
############################ cnss_prealloc ############################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(CNSS_SRC_FILES)
|
||||
LOCAL_MODULE := cnss_prealloc.ko
|
||||
LOCAL_MODULE_KBUILD_NAME := cnss_prealloc/cnss_prealloc.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
############################ cnss_utils ###############################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(CNSS_SRC_FILES)
|
||||
LOCAL_MODULE := cnss_utils.ko
|
||||
LOCAL_MODULE_KBUILD_NAME := cnss_utils/cnss_utils.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
################################ icnss2 ################################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(CNSS_SRC_FILES)
|
||||
LOCAL_MODULE := icnss2.ko
|
||||
LOCAL_MODULE_KBUILD_NAME := icnss2/icnss2.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
endif #ENABLE_WLAN_PLATFORM_DLKM
|
@@ -0,0 +1,34 @@
|
||||
load("//build/kernel/kleaf:kernel.bzl", "ddk_headers")
|
||||
load(":wlan_platform_modules.bzl", "define_modules")
|
||||
|
||||
|
||||
package(
|
||||
default_visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "wlan-platform-headers",
|
||||
hdrs = glob([
|
||||
"inc/*.h",
|
||||
]),
|
||||
includes = ["inc"],
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "wlan-platform-private-headers",
|
||||
hdrs = glob([
|
||||
"cnss2/*.h",
|
||||
"cnss_utils/*.h",
|
||||
"icnss2/*.h"
|
||||
]),
|
||||
includes = ["cnss2", "cnss_utils", "icnss2"],
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "all-wlan-platform-headers",
|
||||
hdrs = [":wlan-platform-headers", ":wlan-platform-private-headers"],
|
||||
)
|
||||
|
||||
define_modules()
|
103
qcom/opensource/wlan/platform/Kbuild
普通文件
103
qcom/opensource/wlan/platform/Kbuild
普通文件
@@ -0,0 +1,103 @@
|
||||
ifeq ($(CONFIG_CNSS_OUT_OF_TREE),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_CNSS_OUT_OF_TREE
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CNSS2_DEBUG),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_CNSS2_DEBUG
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CNSS2_QMI),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_CNSS2_QMI
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ONE_MSI_VECTOR),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_ONE_MSI_VECTOR
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ICNSS2_DEBUG),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_ICNSS2_DEBUG
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ICNSS2_QMI),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_ICNSS2_QMI
|
||||
endif
|
||||
|
||||
# CONFIG_WCNSS_MEM_PRE_ALLOC should never be "y" here since it
|
||||
# can be only compiled as a module from out-of-kernel-tree source.
|
||||
ifeq ($(CONFIG_WCNSS_MEM_PRE_ALLOC),m)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_WCNSS_MEM_PRE_ALLOC
|
||||
endif
|
||||
|
||||
# CONFIG_CNSS_PLAT_IPC_QMI_SVC should never be "y" here since it
|
||||
# can be only compiled as a module from out-of-kernel-tree source.
|
||||
ifeq ($(CONFIG_CNSS_PLAT_IPC_QMI_SVC),m)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_CNSS_PLAT_IPC_QMI_SVC
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CNSS_HW_SECURE_DISABLE), y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_CNSS_HW_SECURE_DISABLE
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CNSS_HW_SECURE_SMEM), y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_CNSS_HW_SECURE_SMEM
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CNSS2_CONDITIONAL_POWEROFF),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_CNSS2_CONDITIONAL_POWEROFF
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CNSS_REQ_FW_DIRECT),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_CNSS_REQ_FW_DIRECT
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CNSS_SUPPORT_DUAL_DEV),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_CNSS_SUPPORT_DUAL_DEV
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_AUTO_PROJECT),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_PULLDOWN_WLANEN
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CNSS2_SSR_DRIVER_DUMP),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_CNSS2_SSR_DRIVER_DUMP
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_FREE_M3_BLOB_MEM),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_FREE_M3_BLOB_MEM
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DISABLE_CNSS_SRAM_DUMP),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_DISABLE_CNSS_SRAM_DUMP
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CNSS2_SMMU_DB_SUPPORT),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_CNSS2_SMMU_DB_SUPPORT
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CNSS2_ENUM_WITH_LOW_SPEED),y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_CNSS2_ENUM_WITH_LOW_SPEED
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SLATE_MODULE_ENABLED), y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_SLATE_MODULE_ENABLED
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_FEATURE_SMEM_MAILBOX), y)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_FEATURE_SMEM_MAILBOX
|
||||
endif
|
||||
|
||||
found = $(shell if grep -qF "int msm_pcie_dsp_link_control" $(srctree)/include/linux/msm_pcie.h; then echo "yes" ;else echo "no" ;fi;)
|
||||
ifeq ($(findstring yes, $(found)), yes)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_PCIE_SWITCH_SUPPORT
|
||||
endif
|
||||
|
||||
found = $(shell if grep -qF "int msm_pcie_retrain_port_link" $(srctree)/include/linux/msm_pcie.h; then echo "yes" ;else echo "no" ;fi;)
|
||||
ifeq ($(findstring yes, $(found)), yes)
|
||||
KBUILD_CPPFLAGS += -DCONFIG_PCIE_SWITCH_RETRAIN_LINK_SUPPORT
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_CNSS2) += cnss2/
|
||||
obj-$(CONFIG_ICNSS2) += icnss2/
|
||||
obj-$(CONFIG_CNSS_GENL) += cnss_genl/
|
||||
obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += cnss_prealloc/
|
||||
obj-y += cnss_utils/
|
@@ -0,0 +1,48 @@
|
||||
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
|
||||
M ?= $(shell pwd)
|
||||
|
||||
# $(WLAN_PLATFORM_ROOT) has to be a absolute path
|
||||
ifeq ($(WLAN_PLATFORM_ROOT),)
|
||||
WLAN_PLATFORM_ROOT = $(shell pwd)
|
||||
|
||||
# If it reaches here, compilation is probably without Android.mk,
|
||||
# so enable all flags (including debug flag CONFIG_CNSS2_DEBUG) by
|
||||
# default.
|
||||
KBUILD_OPTIONS := WLAN_PLATFORM_ROOT=$(WLAN_PLATFORM_ROOT)
|
||||
ifeq ($(WLAN_BASEMACHINE),qcs40x)
|
||||
KBUILD_OPTIONS += CONFIG_CNSS_OUT_OF_TREE=y
|
||||
KBUILD_OPTIONS += CONFIG_ICNSS2=m
|
||||
KBUILD_OPTIONS += CONFIG_ICNSS2_QMI=y
|
||||
KBUILD_OPTIONS += CONFIG_ICNSS2_DEBUG=y
|
||||
KBUILD_OPTIONS += CONFIG_CNSS_QMI_SVC=m
|
||||
KBUILD_OPTIONS += CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
KBUILD_OPTIONS += CONFIG_CNSS_UTILS=m
|
||||
KBUILD_OPTIONS += CONFIG_CNSS_GENL=m
|
||||
KBUILD_OPTIONS += CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
else ifeq ($(USE_EXTERNAL_CONFIGS),)
|
||||
KBUILD_OPTIONS += CONFIG_CNSS_OUT_OF_TREE=y
|
||||
KBUILD_OPTIONS += CONFIG_CNSS2=m
|
||||
KBUILD_OPTIONS += CONFIG_ICNSS2=m
|
||||
KBUILD_OPTIONS += CONFIG_CNSS2_QMI=y
|
||||
KBUILD_OPTIONS += CONFIG_ICNSS2_QMI=y
|
||||
KBUILD_OPTIONS += CONFIG_CNSS2_DEBUG=y
|
||||
KBUILD_OPTIONS += CONFIG_ICNSS2_DEBUG=y
|
||||
KBUILD_OPTIONS += CONFIG_CNSS_QMI_SVC=m
|
||||
KBUILD_OPTIONS += CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
KBUILD_OPTIONS += CONFIG_CNSS_GENL=m
|
||||
KBUILD_OPTIONS += CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
KBUILD_OPTIONS += CONFIG_CNSS_UTILS=m
|
||||
KBUILD_OPTIONS += CONFIG_CNSS2_SSR_DRIVER_DUMP=y
|
||||
endif
|
||||
endif
|
||||
|
||||
all: modules
|
||||
|
||||
%:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(M) $@ $(KBUILD_OPTIONS)
|
||||
|
||||
modules_install:
|
||||
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(M) modules_install
|
||||
|
||||
clean:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(M) clean
|
@@ -0,0 +1,181 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
config CNSS2
|
||||
tristate "CNSS2 Platform Driver for Wi-Fi Module"
|
||||
depends on !CNSS && PCI_MSM
|
||||
select CNSS_PLAT_IPC_QMI_SVC
|
||||
help
|
||||
This module adds the support for Connectivity Subsystem (CNSS) used
|
||||
for PCIe based Wi-Fi devices with QCA6174/QCA6290 chipsets.
|
||||
This driver also adds support to integrate WLAN module to subsystem
|
||||
restart framework.
|
||||
|
||||
config CNSS2_DEBUG
|
||||
bool "CNSS2 Platform Driver Debug Support"
|
||||
depends on CNSS2
|
||||
help
|
||||
This option is to enable CNSS2 platform driver debug support which
|
||||
primarily includes providing additional verbose logs for certain
|
||||
features, enabling kernel panic for certain cases to aid the
|
||||
debugging, and enabling any other debug mechanisms.
|
||||
|
||||
config CNSS2_QMI
|
||||
bool "CNSS2 Platform Driver QMI support"
|
||||
select CNSS_QMI_SVC
|
||||
depends on CNSS2
|
||||
help
|
||||
CNSS2 platform driver uses QMI framework to communicate with WLAN
|
||||
firmware. It sends and receives boot handshake messages to WLAN
|
||||
firmware, which includes hardware and software capabilities and
|
||||
configurations. It also sends WLAN on/off control message to
|
||||
firmware over QMI channel.
|
||||
|
||||
config CNSS_ASYNC
|
||||
bool "Enable/disable CNSS platform driver asynchronous probe"
|
||||
depends on CNSS2
|
||||
help
|
||||
If enabled, CNSS platform driver would do asynchronous probe.
|
||||
Using asynchronous probe will allow CNSS platform driver to
|
||||
probe in parallel with other device drivers and will help to
|
||||
reduce kernel boot time.
|
||||
|
||||
config BUS_AUTO_SUSPEND
|
||||
bool "Enable/Disable Runtime PM support for PCIe based WLAN Drivers"
|
||||
depends on CNSS2
|
||||
depends on PCI
|
||||
help
|
||||
Runtime Power Management is supported for PCIe based WLAN Drivers.
|
||||
The features enable cld wlan driver to suspend pcie bus when APPS
|
||||
is awake based on the driver inactivity with the Firmware.
|
||||
The Feature uses runtime power management framework from kernel to
|
||||
track bus access clients and to synchronize the driver activity
|
||||
during system pm.
|
||||
This config flag controls the feature per target based. The feature
|
||||
requires CNSS driver support.
|
||||
|
||||
config CNSS_QCA6290
|
||||
bool "Enable CNSS QCA6290 chipset specific changes"
|
||||
depends on CNSS2
|
||||
help
|
||||
This enables the changes from WLAN host driver that are specific to
|
||||
CNSS QCA6290 chipset.
|
||||
These changes are needed to support the new hardware architecture
|
||||
for CNSS QCA6290 chipset.
|
||||
|
||||
config CNSS_QCA6390
|
||||
bool "Enable CNSS QCA6390 chipset specific changes"
|
||||
depends on CNSS2
|
||||
help
|
||||
This enables the changes from WLAN host driver that are specific to
|
||||
CNSS QCA6390 chipset.
|
||||
These changes are needed to support the new hardware architecture
|
||||
for CNSS QCA6390 chipset.
|
||||
|
||||
config CNSS_EMULATION
|
||||
bool "Enable specific changes for emulation hardware"
|
||||
depends on CNSS2
|
||||
help
|
||||
This enables the changes from WLAN drivers that are specific to
|
||||
emulation hardware.
|
||||
These changes are needed for WLAN drivers to support and meet the
|
||||
requirement of emulation hardware.
|
||||
|
||||
config CNSS_QCA6490
|
||||
bool "Enable CNSS QCA6490 chipset specific changes"
|
||||
depends on CNSS2
|
||||
help
|
||||
This enables the changes from WLAN host driver that are specific to
|
||||
CNSS QCA6490 chipset.
|
||||
These changes are needed to support the new hardware architecture
|
||||
for CNSS QCA6490 chipset.
|
||||
|
||||
config CNSS_REQ_FW_DIRECT
|
||||
bool "Enable request_firmware_direct for firmware or configuration file"
|
||||
depends on CNSS2
|
||||
help
|
||||
This enables calling request_firmware_direct for firmware or
|
||||
configuration file to avoid 60s timeout while search file under user
|
||||
space failure.
|
||||
|
||||
config CNSS_SUPPORT_DUAL_DEV
|
||||
bool "Enable cnss2 support dual wlan card"
|
||||
depends on CNSS2 && !CNSS_ASYNC
|
||||
help
|
||||
This enables the changes from cnss2 platform driver to support dual
|
||||
wlan card attach. Now just supports QCA6390 chip and does not support
|
||||
asynchronous probe.
|
||||
|
||||
config CNSS2_CONDITIONAL_POWEROFF
|
||||
bool "Enable/Disable conditional bus suspend and device power off"
|
||||
depends on CNSS2
|
||||
depends on PCI
|
||||
help
|
||||
Conditional pcie bus suspend and device powering off for wlan after
|
||||
driver probe for the first time.
|
||||
With this feature enabled, pcie bus suspend and device powering off
|
||||
will not take place for certain wlan chipsets after driver probing
|
||||
for the first time to avoid potential subsequent failures during
|
||||
device re-probe(after wlan function driver loaded) under very bad
|
||||
thermal conditions.
|
||||
|
||||
config DISABLE_CNSS_SRAM_DUMP
|
||||
bool "Disable sram_dump"
|
||||
depends on CNSS2
|
||||
depends on CNSS2_DEBUG
|
||||
help
|
||||
If enabled, CNSS plafrom driver will not dump sram when MHI power on
|
||||
timeout for CNSS QCA6490 chipset only. Since this feature about
|
||||
sram dump costs 4M memory.
|
||||
|
||||
config CNSS2_SMMU_DB_SUPPORT
|
||||
bool "Enable early trace stop support"
|
||||
depends on CNSS2
|
||||
help
|
||||
If enabled, CNSS platform driver will notify wlan fw to stop
|
||||
traces by ringing MHI host doorbell register. This feature helps
|
||||
to get traces which contain smmu fault address and enables
|
||||
debugging.
|
||||
|
||||
config CNSS_HW_SECURE_DISABLE
|
||||
bool "Enable HW secure disable"
|
||||
depends on CNSS2
|
||||
help
|
||||
If enabled, WLAN HW can be securely disabled. It would be able to
|
||||
handle WLAN cold boot initialization sequence changes if HW is
|
||||
disabled at boot and WLAN resume sequence after WLAN HW is enabled.
|
||||
|
||||
config CNSS_HW_SECURE_SMEM
|
||||
bool "Enable SMEM API based HW peripheral security"
|
||||
depends on CNSS2
|
||||
help
|
||||
If enabled, CNSS platform driver will use SMEM APIs intead of SCM
|
||||
APIs to check peripheral secure state of HW.
|
||||
|
||||
config CNSS2_SSR_DRIVER_DUMP
|
||||
bool "Enable Host SSR DRIVER DUMP Collection"
|
||||
depends on CNSS2
|
||||
help
|
||||
If enabled, host driver dump will be collected upon SSR.
|
||||
|
||||
config CNSS_OUT_OF_TREE
|
||||
bool "Enable Out of Tree Usage"
|
||||
depends on CNSS2
|
||||
help
|
||||
If enabled, CNSS platform driver modules would be able to access
|
||||
functions from the other modules in the platform driver.
|
||||
|
||||
config WCNSS_MEM_PRE_ALLOC
|
||||
tristate "WCNSS pre-alloc memory support"
|
||||
help
|
||||
Pre-allocate memory for the WLAN driver module.
|
||||
This feature enable cld wlan driver to use pre allocated memory
|
||||
for it's internal usage and release it to back to pre allocated pool.
|
||||
This memory is allocated at the cold boot time.
|
||||
|
||||
config CNSS2_ENUM_WITH_LOW_SPEED
|
||||
bool "Enable/Disable enumurate with low speed feature"
|
||||
depends on CNSS2
|
||||
depends on PCI
|
||||
help
|
||||
Set link target speed to Gen1 before enum, and then restore default
|
||||
RC speed to re-establish link speed. For Genoa chip, needn't restore.
|
@@ -0,0 +1,28 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
ccflags-y += -Wmissing-prototypes
|
||||
|
||||
ifeq ($(CONFIG_CNSS_OUT_OF_TREE),y)
|
||||
ccflags-y += -I$(WLAN_PLATFORM_ROOT)/cnss_utils
|
||||
ccflags-y += -I$(WLAN_PLATFORM_ROOT)/inc
|
||||
else
|
||||
ccflags-y += -I$(srctree)/drivers/net/wireless/cnss_utils
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CNSS_HW_SECURE_DISABLE), y)
|
||||
ccflags-y += -I$(WLAN_PLATFORM_ROOT)/../../securemsm-kernel/smcinvoke/
|
||||
ccflags-y += -I$(WLAN_PLATFORM_ROOT)/../../securemsm-kernel/linux/
|
||||
ccflags-y += -I$(WLAN_PLATFORM_ROOT)/../../securemsm-kernel/include/linux/
|
||||
ccflags-y += -I$(WLAN_PLATFORM_ROOT)/../../securemsm-kernel/include/uapi/linux/
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_CNSS2) += cnss2.o
|
||||
|
||||
cnss2-y := main.o
|
||||
cnss2-y += bus.o
|
||||
cnss2-y += debug.o
|
||||
cnss2-y += pci.o
|
||||
cnss2-y += power.o
|
||||
cnss2-y += genl.o
|
||||
cnss2-$(CONFIG_PCI_MSM) += pci_qcom.o
|
||||
cnss2-$(CONFIG_CNSS2_QMI) += qmi.o coexistence_service_v01.o
|
@@ -0,0 +1,10 @@
|
||||
CONFIG_CNSS2=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
||||
CONFIG_CNSS2_QMI=y
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_BUS_AUTO_SUSPEND=y
|
||||
CONFIG_CNSS2_SSR_DRIVER_DUMP=y
|
||||
CONFIG_CNSS2_SMMU_DB_SUPPORT=y
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS2_DEBUG=y
|
@@ -0,0 +1,9 @@
|
||||
CONFIG_CNSS2=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
||||
CONFIG_CNSS2_QMI=y
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_BUS_AUTO_SUSPEND=y
|
||||
CONFIG_CNSS2_SSR_DRIVER_DUMP=y
|
||||
CONFIG_CNSS2_SMMU_DB_SUPPORT=y
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
@@ -0,0 +1,868 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "bus.h"
|
||||
#include "debug.h"
|
||||
#include "pci.h"
|
||||
#include "pci_platform.h"
|
||||
|
||||
enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return CNSS_BUS_NONE;
|
||||
|
||||
if (!dev->bus)
|
||||
return CNSS_BUS_NONE;
|
||||
|
||||
if (memcmp(dev->bus->name, "pci", 3) == 0)
|
||||
return CNSS_BUS_PCI;
|
||||
else
|
||||
return CNSS_BUS_NONE;
|
||||
}
|
||||
|
||||
enum cnss_dev_bus_type cnss_get_bus_type(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
int ret;
|
||||
struct device *dev;
|
||||
u32 bus_type_dt = CNSS_BUS_NONE;
|
||||
|
||||
if (plat_priv->dt_type == CNSS_DTT_MULTIEXCHG) {
|
||||
dev = &plat_priv->plat_dev->dev;
|
||||
ret = of_property_read_u32(dev->of_node, "qcom,bus-type",
|
||||
&bus_type_dt);
|
||||
if (!ret)
|
||||
if (bus_type_dt < CNSS_BUS_MAX)
|
||||
cnss_pr_dbg("Got bus type[%u] from dt\n",
|
||||
bus_type_dt);
|
||||
else
|
||||
bus_type_dt = CNSS_BUS_NONE;
|
||||
else
|
||||
cnss_pr_err("No bus type for multi-exchg dt\n");
|
||||
|
||||
return bus_type_dt;
|
||||
}
|
||||
|
||||
switch (plat_priv->device_id) {
|
||||
case QCA6174_DEVICE_ID:
|
||||
case QCA6290_DEVICE_ID:
|
||||
case QCA6390_DEVICE_ID:
|
||||
case QCN7605_DEVICE_ID:
|
||||
case QCA6490_DEVICE_ID:
|
||||
case KIWI_DEVICE_ID:
|
||||
case MANGO_DEVICE_ID:
|
||||
case PEACH_DEVICE_ID:
|
||||
return CNSS_BUS_PCI;
|
||||
default:
|
||||
cnss_pr_err("Unknown device_id: 0x%lx\n", plat_priv->device_id);
|
||||
return CNSS_BUS_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void *cnss_bus_dev_to_bus_priv(struct device *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
switch (cnss_get_dev_bus_type(dev)) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_get_pci_priv(to_pci_dev(dev));
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev)
|
||||
{
|
||||
void *bus_priv;
|
||||
|
||||
if (!dev)
|
||||
return cnss_get_plat_priv(NULL);
|
||||
|
||||
bus_priv = cnss_bus_dev_to_bus_priv(dev);
|
||||
if (!bus_priv)
|
||||
return NULL;
|
||||
|
||||
switch (cnss_get_dev_bus_type(dev)) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_priv_to_plat_priv(bus_priv);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_init(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_init(plat_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
void cnss_bus_deinit(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_deinit(plat_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void cnss_bus_add_fw_prefix_name(struct cnss_plat_data *plat_priv,
|
||||
char *prefix_name, char *name)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_add_fw_prefix_name(plat_priv->bus_priv,
|
||||
prefix_name, name);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_load_tme_patch(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_load_tme_patch(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_load_tme_opt_file(struct cnss_plat_data *plat_priv,
|
||||
enum wlfw_tme_lite_file_type_v01 file)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_load_tme_opt_file(plat_priv->bus_priv, file);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_load_m3(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_load_m3(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_load_aux(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_load_aux(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_handle_dev_sol_irq(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_handle_dev_sol_irq(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_alloc_fw_mem(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_alloc_fw_mem(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_alloc_qdss_mem(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_alloc_qdss_mem(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
void cnss_bus_free_qdss_mem(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
cnss_pci_free_qdss_mem(plat_priv->bus_priv);
|
||||
return;
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
u32 cnss_bus_get_wake_irq(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_get_wake_msi(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_force_fw_assert_hdlr(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_force_fw_assert_hdlr(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_qmi_send_get(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_qmi_send_get(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_qmi_send_put(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_qmi_send_put(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
void cnss_bus_fw_boot_timeout_hdlr(struct timer_list *t)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv =
|
||||
from_timer(plat_priv, t, fw_boot_timer);
|
||||
|
||||
if (!plat_priv)
|
||||
return;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_fw_boot_timeout_hdlr(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void cnss_bus_collect_dump_info(struct cnss_plat_data *plat_priv, bool in_panic)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_collect_dump_info(plat_priv->bus_priv,
|
||||
in_panic);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void cnss_bus_device_crashed(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_device_crashed(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_call_driver_probe(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_call_driver_probe(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_call_driver_remove(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_call_driver_remove(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_dev_powerup(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_dev_powerup(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_dev_shutdown(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_dev_shutdown(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_dev_crash_shutdown(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_dev_crash_shutdown(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_dev_ramdump(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_dev_ramdump(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_register_driver_hdlr(struct cnss_plat_data *plat_priv, void *data)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_register_driver_hdlr(plat_priv->bus_priv, data);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_runtime_pm_get_sync(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_pm_runtime_get_sync(plat_priv->bus_priv, RTPM_ID_CNSS);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
void cnss_bus_runtime_pm_put(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
cnss_pci_pm_runtime_mark_last_busy(plat_priv->bus_priv);
|
||||
cnss_pci_pm_runtime_put_autosuspend(plat_priv->bus_priv, RTPM_ID_CNSS);
|
||||
break;
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_unregister_driver_hdlr(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_unregister_driver_hdlr(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_call_driver_modem_status(struct cnss_plat_data *plat_priv,
|
||||
int modem_current_status)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_call_driver_modem_status(plat_priv->bus_priv,
|
||||
modem_current_status);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_update_status(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_driver_status status)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_update_status(plat_priv->bus_priv, status);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_update_uevent(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_driver_status status, void *data)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_call_driver_uevent(plat_priv->bus_priv,
|
||||
status, data);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_is_device_down(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pcie_is_device_down(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_dbg("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_shutdown_cleanup(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_shutdown_cleanup(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_dbg("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_check_link_status(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_check_link_status(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_dbg("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_recover_link_down(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_recover_link_down(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_dbg("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_debug_reg_read(struct cnss_plat_data *plat_priv, u32 offset,
|
||||
u32 *val, bool raw_access)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_debug_reg_read(plat_priv->bus_priv, offset,
|
||||
val, raw_access);
|
||||
default:
|
||||
cnss_pr_dbg("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_debug_reg_write(struct cnss_plat_data *plat_priv, u32 offset,
|
||||
u32 val, bool raw_access)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_debug_reg_write(plat_priv->bus_priv, offset,
|
||||
val, raw_access);
|
||||
default:
|
||||
cnss_pr_dbg("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_get_iova(struct cnss_plat_data *plat_priv, u64 *addr, u64 *size)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_get_iova(plat_priv->bus_priv, addr, size);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_get_iova_ipa(struct cnss_plat_data *plat_priv, u64 *addr,
|
||||
u64 *size)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_get_iova_ipa(plat_priv->bus_priv, addr, size);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
bool cnss_bus_is_smmu_s1_enabled(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return false;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_is_smmu_s1_enabled(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_dsp_link_control(struct cnss_plat_data *plat_priv,
|
||||
bool link_enable)
|
||||
{
|
||||
if (!plat_priv || plat_priv->pcie_switch_type != PCIE_SWITCH_NTN3)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_dsp_link_control(plat_priv->bus_priv, link_enable);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_set_dsp_link_status(struct cnss_plat_data *plat_priv,
|
||||
bool link_enable)
|
||||
{
|
||||
if (!plat_priv || plat_priv->pcie_switch_type != PCIE_SWITCH_NTN3)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_set_dsp_link_status(plat_priv->bus_priv, link_enable);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_get_dsp_link_status(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv || plat_priv->pcie_switch_type != PCIE_SWITCH_NTN3)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_get_dsp_link_status(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_dsp_link_enable(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv || plat_priv->pcie_switch_type != PCIE_SWITCH_NTN3)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_dsp_link_enable(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_update_time_sync_period(struct cnss_plat_data *plat_priv,
|
||||
unsigned int time_sync_period)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_update_time_sync_period(plat_priv->bus_priv,
|
||||
time_sync_period);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_set_therm_cdev_state(struct cnss_plat_data *plat_priv,
|
||||
unsigned long thermal_state,
|
||||
int tcdev_id)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_set_therm_cdev_state(plat_priv->bus_priv,
|
||||
thermal_state,
|
||||
tcdev_id);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n", plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_get_msi_assignment(struct cnss_plat_data *plat_priv,
|
||||
char *msi_name,
|
||||
int *num_vectors,
|
||||
u32 *user_base_data,
|
||||
u32 *base_vector)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_get_user_msi_assignment(plat_priv->bus_priv,
|
||||
msi_name,
|
||||
num_vectors,
|
||||
user_base_data,
|
||||
base_vector);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n", plat_priv->bus_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_MHI_BUS_MISC)
|
||||
void cnss_bus_disable_mhi_satellite_cfg(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
struct cnss_pci_data *pci_priv;
|
||||
|
||||
pci_priv = plat_priv->bus_priv;
|
||||
if (!pci_priv) {
|
||||
cnss_pr_err("mhi satellite could not be disabled since pci_priv is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
/* MHI satellite configuration is only for KIWI V2 and
|
||||
* that too only in DRV mode.
|
||||
*/
|
||||
if (plat_priv->device_id == KIWI_DEVICE_ID &&
|
||||
plat_priv->device_version.major_version == FW_V2_NUMBER) {
|
||||
cnss_pr_dbg("Remove MHI satellite configuration\n");
|
||||
return cnss_mhi_controller_set_base(pci_priv, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cnss_pr_dbg("Unsupported bus type: %d, ignore disable mhi satellite cfg\n",
|
||||
plat_priv->bus_type);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#else
|
||||
void cnss_bus_disable_mhi_satellite_cfg(struct cnss_plat_data *pci_priv)
|
||||
{
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,86 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CNSS_BUS_H
|
||||
#define _CNSS_BUS_H
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#define QCA6174_REV_ID_OFFSET 0x08
|
||||
#define QCA6174_REV3_VERSION 0x5020000
|
||||
#define QCA6174_REV3_2_VERSION 0x5030000
|
||||
|
||||
enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev);
|
||||
enum cnss_dev_bus_type cnss_get_bus_type(struct cnss_plat_data *plat_priv);
|
||||
void *cnss_bus_dev_to_bus_priv(struct device *dev);
|
||||
struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev);
|
||||
int cnss_bus_init(struct cnss_plat_data *plat_priv);
|
||||
void cnss_bus_deinit(struct cnss_plat_data *plat_priv);
|
||||
void cnss_bus_add_fw_prefix_name(struct cnss_plat_data *plat_priv,
|
||||
char *prefix_name, char *name);
|
||||
int cnss_bus_load_tme_patch(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_load_tme_opt_file(struct cnss_plat_data *plat_priv,
|
||||
enum wlfw_tme_lite_file_type_v01 file);
|
||||
int cnss_bus_runtime_pm_get_sync(struct cnss_plat_data *plat_priv);
|
||||
void cnss_bus_runtime_pm_put(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_load_m3(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_load_aux(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_handle_dev_sol_irq(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_alloc_fw_mem(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_alloc_qdss_mem(struct cnss_plat_data *plat_priv);
|
||||
void cnss_bus_free_qdss_mem(struct cnss_plat_data *plat_priv);
|
||||
u32 cnss_bus_get_wake_irq(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_force_fw_assert_hdlr(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_qmi_send_get(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_qmi_send_put(struct cnss_plat_data *plat_priv);
|
||||
void cnss_bus_fw_boot_timeout_hdlr(struct timer_list *t);
|
||||
void cnss_bus_collect_dump_info(struct cnss_plat_data *plat_priv,
|
||||
bool in_panic);
|
||||
void cnss_bus_device_crashed(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_call_driver_probe(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_call_driver_remove(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_dev_powerup(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_dev_shutdown(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_dev_crash_shutdown(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_dev_ramdump(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_register_driver_hdlr(struct cnss_plat_data *plat_priv, void *data);
|
||||
int cnss_bus_unregister_driver_hdlr(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_call_driver_modem_status(struct cnss_plat_data *plat_priv,
|
||||
int modem_current_status);
|
||||
int cnss_bus_update_status(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_driver_status status);
|
||||
int cnss_bus_update_uevent(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_driver_status status, void *data);
|
||||
int cnss_bus_is_device_down(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_shutdown_cleanup(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_check_link_status(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_recover_link_down(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_debug_reg_read(struct cnss_plat_data *plat_priv, u32 offset,
|
||||
u32 *val, bool raw_access);
|
||||
int cnss_bus_debug_reg_write(struct cnss_plat_data *plat_priv, u32 offset,
|
||||
u32 val, bool raw_access);
|
||||
int cnss_bus_get_iova(struct cnss_plat_data *plat_priv, u64 *addr, u64 *size);
|
||||
int cnss_bus_get_iova_ipa(struct cnss_plat_data *plat_priv, u64 *addr,
|
||||
u64 *size);
|
||||
bool cnss_bus_is_smmu_s1_enabled(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_update_time_sync_period(struct cnss_plat_data *plat_priv,
|
||||
unsigned int time_sync_period);
|
||||
void cnss_bus_disable_mhi_satellite_cfg(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_set_therm_cdev_state(struct cnss_plat_data *plat_priv,
|
||||
unsigned long thermal_state,
|
||||
int tcdev_id);
|
||||
int cnss_bus_get_msi_assignment(struct cnss_plat_data *plat_priv,
|
||||
char *msi_name,
|
||||
int *num_vectors,
|
||||
u32 *user_base_data,
|
||||
u32 *base_vector);
|
||||
int cnss_bus_dsp_link_control(struct cnss_plat_data *plat_priv,
|
||||
bool link_enable);
|
||||
int cnss_bus_set_dsp_link_status(struct cnss_plat_data *plat_priv,
|
||||
bool link_enable);
|
||||
int cnss_bus_get_dsp_link_status(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_dsp_link_enable(struct cnss_plat_data *plat_priv);
|
||||
#endif /* _CNSS_BUS_H */
|
@@ -0,0 +1,100 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#include <linux/soc/qcom/qmi.h>
|
||||
|
||||
#include "coexistence_service_v01.h"
|
||||
|
||||
struct qmi_elem_info coex_antenna_switch_to_wlan_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u64),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset = offsetof(struct
|
||||
coex_antenna_switch_to_wlan_req_msg_v01,
|
||||
antenna),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info coex_antenna_switch_to_wlan_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct
|
||||
coex_antenna_switch_to_wlan_resp_msg_v01,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct
|
||||
coex_antenna_switch_to_wlan_resp_msg_v01,
|
||||
grant_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u64),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct
|
||||
coex_antenna_switch_to_wlan_resp_msg_v01,
|
||||
grant),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info coex_antenna_switch_to_mdm_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u64),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset = offsetof(struct
|
||||
coex_antenna_switch_to_mdm_req_msg_v01,
|
||||
antenna),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info coex_antenna_switch_to_mdm_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct
|
||||
coex_antenna_switch_to_mdm_resp_msg_v01,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
@@ -0,0 +1,52 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2019, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef COEXISTENCE_SERVICE_V01_H
|
||||
#define COEXISTENCE_SERVICE_V01_H
|
||||
|
||||
#define COEX_SERVICE_ID_V01 0x22
|
||||
#define COEX_SERVICE_VERS_V01 0x01
|
||||
|
||||
#define COEX_SERVICE_MAX_MSG_LEN 8204
|
||||
|
||||
#define QMI_COEX_SWITCH_ANTENNA_TO_WLAN_RESP_V01 0x0042
|
||||
#define QMI_COEX_SWITCH_ANTENNA_TO_WLAN_REQ_V01 0x0042
|
||||
#define QMI_COEX_SWITCH_ANTENNA_TO_MDM_RESP_V01 0x0042
|
||||
#define QMI_COEX_SWITCH_ANTENNA_TO_MDM_REQ_V01 0x0042
|
||||
|
||||
#define COEX_ANTENNA_BAND_2GHZ_CHAIN0_V01 ((u64)0x0000000000000001ULL)
|
||||
#define COEX_ANTENNA_BAND_2GHZ_CHAIN1_V01 ((u64)0x0000000000000002ULL)
|
||||
#define COEX_ANTENNA_BAND_5GHZ_CHAIN0_V01 ((u64)0x0000000000000004ULL)
|
||||
#define COEX_ANTENNA_BAND_5GHZ_CHAIN1_V01 ((u64)0x0000000000000008ULL)
|
||||
|
||||
struct coex_antenna_switch_to_wlan_req_msg_v01 {
|
||||
u64 antenna;
|
||||
};
|
||||
|
||||
#define COEX_ANTENNA_SWITCH_TO_WLAN_REQ_MSG_V01_MAX_MSG_LEN 11
|
||||
extern struct qmi_elem_info coex_antenna_switch_to_wlan_req_msg_v01_ei[];
|
||||
|
||||
struct coex_antenna_switch_to_wlan_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
u8 grant_valid;
|
||||
u64 grant;
|
||||
};
|
||||
|
||||
#define COEX_ANTENNA_SWITCH_TO_WLAN_RESP_MSG_V01_MAX_MSG_LEN 18
|
||||
extern struct qmi_elem_info coex_antenna_switch_to_wlan_resp_msg_v01_ei[];
|
||||
|
||||
struct coex_antenna_switch_to_mdm_req_msg_v01 {
|
||||
u64 antenna;
|
||||
};
|
||||
|
||||
#define COEX_ANTENNA_SWITCH_TO_MDM_REQ_MSG_V01_MAX_MSG_LEN 11
|
||||
extern struct qmi_elem_info coex_antenna_switch_to_mdm_req_msg_v01_ei[];
|
||||
|
||||
struct coex_antenna_switch_to_mdm_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
|
||||
#define COEX_ANTENNA_SWITCH_TO_MDM_RESP_MSG_V01_MAX_MSG_LEN 7
|
||||
extern struct qmi_elem_info coex_antenna_switch_to_mdm_resp_msg_v01_ei[];
|
||||
|
||||
#endif
|
文件差异内容过多而无法显示
加载差异
@@ -0,0 +1,108 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
|
||||
/* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */
|
||||
|
||||
#ifndef _CNSS_DEBUG_H
|
||||
#define _CNSS_DEBUG_H
|
||||
|
||||
#include <linux/printk.h>
|
||||
|
||||
enum log_level {
|
||||
EMERG_LOG = 0,
|
||||
ALERT_LOG = 1,
|
||||
CRIT_LOG = 2,
|
||||
ERR_LOG = 3,
|
||||
WARNING_LOG = 4,
|
||||
NOTICE_LOG = 5,
|
||||
INFO_LOG = 6,
|
||||
DEBUG_LOG = 7,
|
||||
DEBUG_HI_LOG = 8,
|
||||
MAX_LOG = 9,
|
||||
};
|
||||
|
||||
extern enum log_level cnss_kernel_log_level;
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPC_LOGGING)
|
||||
#include <linux/ipc_logging.h>
|
||||
#include <asm/current.h>
|
||||
|
||||
extern void *cnss_ipc_log_context;
|
||||
extern void *cnss_ipc_log_long_context;
|
||||
extern enum log_level cnss_ipc_log_level;
|
||||
|
||||
#ifdef CONFIG_CNSS2_DEBUG
|
||||
#define CNSS_IPC_LOG_PAGES 100
|
||||
#else
|
||||
#define CNSS_IPC_LOG_PAGES 50
|
||||
#endif
|
||||
#define cnss_debug_log_print(_x...) \
|
||||
cnss_debug_ipc_log_print(cnss_ipc_log_context, _x)
|
||||
|
||||
#define cnss_debug_log_long_print(_x...) \
|
||||
cnss_debug_ipc_log_print(cnss_ipc_log_long_context, _x)
|
||||
#else
|
||||
#define cnss_debug_log_print(_x...) \
|
||||
cnss_debug_ipc_log_print((void *)NULL, _x)
|
||||
#define cnss_debug_log_long_print(_x...) \
|
||||
cnss_debug_ipc_log_print((void *)NULL, _x)
|
||||
#endif
|
||||
|
||||
#define proc_name (in_irq() ? "irq" : \
|
||||
(in_softirq() ? "soft_irq" : current->comm))
|
||||
|
||||
#define cnss_pr_err(_fmt, ...) \
|
||||
cnss_debug_log_print(proc_name, __func__, \
|
||||
ERR_LOG, ERR_LOG, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#define cnss_pr_warn(_fmt, ...) \
|
||||
cnss_debug_log_print(proc_name, __func__, \
|
||||
WARNING_LOG, WARNING_LOG, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#define cnss_pr_info(_fmt, ...) \
|
||||
cnss_debug_log_print(proc_name, __func__, \
|
||||
INFO_LOG, INFO_LOG, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#define cnss_pr_dbg(_fmt, ...) \
|
||||
cnss_debug_log_print(proc_name, __func__, \
|
||||
DEBUG_LOG, DEBUG_LOG, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#define cnss_pr_vdbg(_fmt, ...) \
|
||||
cnss_debug_log_long_print(proc_name, __func__, \
|
||||
DEBUG_LOG, DEBUG_LOG, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#define cnss_pr_buf(_fmt, ...) \
|
||||
cnss_debug_log_long_print(proc_name, __func__, \
|
||||
DEBUG_HI_LOG, DEBUG_LOG, _fmt, ##__VA_ARGS__)
|
||||
#define cnss_pr_dbg_buf(_fmt, ...) \
|
||||
cnss_debug_log_long_print(proc_name, __func__, \
|
||||
DEBUG_HI_LOG, DEBUG_HI_LOG, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#ifdef CONFIG_CNSS2_DEBUG
|
||||
#define CNSS_ASSERT(_condition) do { \
|
||||
if (!(_condition)) { \
|
||||
cnss_pr_err("ASSERT at line %d\n", \
|
||||
__LINE__); \
|
||||
BUG(); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define CNSS_ASSERT(_condition) do { \
|
||||
if (!(_condition)) { \
|
||||
cnss_pr_err("ASSERT at line %d\n", \
|
||||
__LINE__); \
|
||||
WARN_ON(1); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define cnss_fatal_err(_fmt, ...) \
|
||||
cnss_pr_err("fatal: " _fmt, ##__VA_ARGS__)
|
||||
|
||||
int cnss_debug_init(void);
|
||||
void cnss_debug_deinit(void);
|
||||
int cnss_debugfs_create(struct cnss_plat_data *plat_priv);
|
||||
void cnss_debugfs_destroy(struct cnss_plat_data *plat_priv);
|
||||
void cnss_debug_ipc_log_print(void *log_ctx, char *process, const char *fn,
|
||||
enum log_level kern_log_level,
|
||||
enum log_level ipc_log_level, char *fmt, ...);
|
||||
#endif /* _CNSS_DEBUG_H */
|
@@ -0,0 +1,217 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "cnss_genl: " fmt
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/genetlink.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "debug.h"
|
||||
#include "genl.h"
|
||||
|
||||
#define CNSS_GENL_FAMILY_NAME "cnss-genl"
|
||||
#define CNSS_GENL_MCAST_GROUP_NAME "cnss-genl-grp"
|
||||
#define CNSS_GENL_VERSION 1
|
||||
#define CNSS_GENL_DATA_LEN_MAX (15 * 1024)
|
||||
#define CNSS_GENL_STR_LEN_MAX 16
|
||||
|
||||
enum {
|
||||
CNSS_GENL_ATTR_MSG_UNSPEC,
|
||||
CNSS_GENL_ATTR_MSG_TYPE,
|
||||
CNSS_GENL_ATTR_MSG_FILE_NAME,
|
||||
CNSS_GENL_ATTR_MSG_TOTAL_SIZE,
|
||||
CNSS_GENL_ATTR_MSG_SEG_ID,
|
||||
CNSS_GENL_ATTR_MSG_END,
|
||||
CNSS_GENL_ATTR_MSG_DATA_LEN,
|
||||
CNSS_GENL_ATTR_MSG_DATA,
|
||||
__CNSS_GENL_ATTR_MAX,
|
||||
};
|
||||
|
||||
#define CNSS_GENL_ATTR_MAX (__CNSS_GENL_ATTR_MAX - 1)
|
||||
|
||||
enum {
|
||||
CNSS_GENL_CMD_UNSPEC,
|
||||
CNSS_GENL_CMD_MSG,
|
||||
__CNSS_GENL_CMD_MAX,
|
||||
};
|
||||
|
||||
#define CNSS_GENL_CMD_MAX (__CNSS_GENL_CMD_MAX - 1)
|
||||
|
||||
static struct nla_policy cnss_genl_msg_policy[CNSS_GENL_ATTR_MAX + 1] = {
|
||||
[CNSS_GENL_ATTR_MSG_TYPE] = { .type = NLA_U8 },
|
||||
[CNSS_GENL_ATTR_MSG_FILE_NAME] = { .type = NLA_NUL_STRING,
|
||||
.len = CNSS_GENL_STR_LEN_MAX },
|
||||
[CNSS_GENL_ATTR_MSG_TOTAL_SIZE] = { .type = NLA_U32 },
|
||||
[CNSS_GENL_ATTR_MSG_SEG_ID] = { .type = NLA_U32 },
|
||||
[CNSS_GENL_ATTR_MSG_END] = { .type = NLA_U8 },
|
||||
[CNSS_GENL_ATTR_MSG_DATA_LEN] = { .type = NLA_U32 },
|
||||
[CNSS_GENL_ATTR_MSG_DATA] = { .type = NLA_BINARY,
|
||||
.len = CNSS_GENL_DATA_LEN_MAX },
|
||||
};
|
||||
|
||||
static int cnss_genl_process_msg(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct genl_ops cnss_genl_ops[] = {
|
||||
{
|
||||
.cmd = CNSS_GENL_CMD_MSG,
|
||||
.doit = cnss_genl_process_msg,
|
||||
},
|
||||
};
|
||||
|
||||
static struct genl_multicast_group cnss_genl_mcast_grp[] = {
|
||||
{
|
||||
.name = CNSS_GENL_MCAST_GROUP_NAME,
|
||||
},
|
||||
};
|
||||
|
||||
static struct genl_family cnss_genl_family = {
|
||||
.id = 0,
|
||||
.hdrsize = 0,
|
||||
.name = CNSS_GENL_FAMILY_NAME,
|
||||
.version = CNSS_GENL_VERSION,
|
||||
.maxattr = CNSS_GENL_ATTR_MAX,
|
||||
.policy = cnss_genl_msg_policy,
|
||||
.module = THIS_MODULE,
|
||||
.ops = cnss_genl_ops,
|
||||
.n_ops = ARRAY_SIZE(cnss_genl_ops),
|
||||
.mcgrps = cnss_genl_mcast_grp,
|
||||
.n_mcgrps = ARRAY_SIZE(cnss_genl_mcast_grp),
|
||||
};
|
||||
|
||||
static int cnss_genl_send_data(u8 type, char *file_name, u32 total_size,
|
||||
u32 seg_id, u8 end, u32 data_len, u8 *msg_buff)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
void *msg_header = NULL;
|
||||
int ret = 0;
|
||||
char filename[CNSS_GENL_STR_LEN_MAX + 1];
|
||||
|
||||
cnss_pr_dbg_buf("type: %u, file_name %s, total_size: %x, seg_id %u, end %u, data_len %u\n",
|
||||
type, file_name, total_size, seg_id, end, data_len);
|
||||
|
||||
if (!file_name)
|
||||
strlcpy(filename, "default", sizeof(filename));
|
||||
else
|
||||
strlcpy(filename, file_name, sizeof(filename));
|
||||
|
||||
skb = genlmsg_new(NLMSG_HDRLEN +
|
||||
nla_total_size(sizeof(type)) +
|
||||
nla_total_size(strlen(filename) + 1) +
|
||||
nla_total_size(sizeof(total_size)) +
|
||||
nla_total_size(sizeof(seg_id)) +
|
||||
nla_total_size(sizeof(end)) +
|
||||
nla_total_size(sizeof(data_len)) +
|
||||
nla_total_size(data_len), GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
msg_header = genlmsg_put(skb, 0, 0,
|
||||
&cnss_genl_family, 0,
|
||||
CNSS_GENL_CMD_MSG);
|
||||
if (!msg_header) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = nla_put_u8(skb, CNSS_GENL_ATTR_MSG_TYPE, type);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
ret = nla_put_string(skb, CNSS_GENL_ATTR_MSG_FILE_NAME, filename);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
ret = nla_put_u32(skb, CNSS_GENL_ATTR_MSG_TOTAL_SIZE, total_size);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
ret = nla_put_u32(skb, CNSS_GENL_ATTR_MSG_SEG_ID, seg_id);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
ret = nla_put_u8(skb, CNSS_GENL_ATTR_MSG_END, end);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
ret = nla_put_u32(skb, CNSS_GENL_ATTR_MSG_DATA_LEN, data_len);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
ret = nla_put(skb, CNSS_GENL_ATTR_MSG_DATA, data_len, msg_buff);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
genlmsg_end(skb, msg_header);
|
||||
ret = genlmsg_multicast(&cnss_genl_family, skb, 0, 0, GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
cnss_pr_err("Fail to send genl msg: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
fail:
|
||||
cnss_pr_err("Fail to generate genl msg: %d\n", ret);
|
||||
if (skb)
|
||||
nlmsg_free(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cnss_genl_send_msg(void *buff, u8 type, char *file_name, u32 total_size)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 *msg_buff = buff;
|
||||
u32 remaining = total_size;
|
||||
u32 seg_id = 0;
|
||||
u32 data_len = 0;
|
||||
u8 end = 0;
|
||||
u8 retry;
|
||||
|
||||
cnss_pr_dbg_buf("type: %u, total_size: %x\n", type, total_size);
|
||||
|
||||
while (remaining) {
|
||||
if (remaining > CNSS_GENL_DATA_LEN_MAX) {
|
||||
data_len = CNSS_GENL_DATA_LEN_MAX;
|
||||
} else {
|
||||
data_len = remaining;
|
||||
end = 1;
|
||||
}
|
||||
|
||||
for (retry = 0; retry < 2; retry++) {
|
||||
ret = cnss_genl_send_data(type, file_name, total_size,
|
||||
seg_id, end, data_len,
|
||||
msg_buff);
|
||||
if (ret >= 0)
|
||||
break;
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
cnss_pr_err("fail to send genl data, ret %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
remaining -= data_len;
|
||||
msg_buff += data_len;
|
||||
seg_id++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cnss_genl_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = genl_register_family(&cnss_genl_family);
|
||||
if (ret != 0)
|
||||
cnss_pr_err("genl_register_family fail: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cnss_genl_exit(void)
|
||||
{
|
||||
genl_unregister_family(&cnss_genl_family);
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef __CNSS_GENL_H__
|
||||
#define __CNSS_GENL_H__
|
||||
|
||||
enum cnss_genl_msg_type {
|
||||
CNSS_GENL_MSG_TYPE_UNSPEC,
|
||||
CNSS_GENL_MSG_TYPE_QDSS,
|
||||
};
|
||||
|
||||
int cnss_genl_init(void);
|
||||
void cnss_genl_exit(void);
|
||||
int cnss_genl_send_msg(void *buff, u8 type,
|
||||
char *file_name, u32 total_size);
|
||||
|
||||
#endif
|
文件差异内容过多而无法显示
加载差异
@@ -0,0 +1,772 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CNSS_MAIN_H
|
||||
#define _CNSS_MAIN_H
|
||||
|
||||
#if IS_ENABLED(CONFIG_ARM) || IS_ENABLED(CONFIG_ARM64)
|
||||
#include <asm/arch_timer.h>
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_ESOC)
|
||||
#include <linux/esoc_client.h>
|
||||
#endif
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/firmware.h>
|
||||
#if IS_ENABLED(CONFIG_INTERCONNECT)
|
||||
#include <linux/interconnect.h>
|
||||
#endif
|
||||
#include <linux/mailbox_client.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/time64.h>
|
||||
#if IS_ENABLED(CONFIG_MSM_QMP)
|
||||
#include <linux/mailbox/qmp.h>
|
||||
#endif
|
||||
#ifdef CONFIG_CNSS_OUT_OF_TREE
|
||||
#include "cnss2.h"
|
||||
#else
|
||||
#include <net/cnss2.h>
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2) || IS_ENABLED(CONFIG_QCOM_MINIDUMP)
|
||||
#include <soc/qcom/memory_dump.h>
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART) || \
|
||||
IS_ENABLED(CONFIG_QCOM_RAMDUMP)
|
||||
#include <soc/qcom/qcom_ramdump.h>
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
|
||||
#include <soc/qcom/subsystem_notif.h>
|
||||
#include <soc/qcom/subsystem_restart.h>
|
||||
#endif
|
||||
#include <linux/iommu.h>
|
||||
#include "qmi.h"
|
||||
#include "cnss_prealloc.h"
|
||||
#include "cnss_common.h"
|
||||
|
||||
#define MAX_NO_OF_MAC_ADDR 4
|
||||
#define QMI_WLFW_MAX_TIMESTAMP_LEN 32
|
||||
#define QMI_WLFW_MAX_BUILD_ID_LEN 128
|
||||
#define CNSS_RDDM_TIMEOUT_MS 20000
|
||||
#define RECOVERY_TIMEOUT 60000
|
||||
#define WLAN_WD_TIMEOUT_MS 60000
|
||||
#define WLAN_COLD_BOOT_CAL_TIMEOUT 60000
|
||||
#define WLAN_MISSION_MODE_TIMEOUT 30000
|
||||
#define TIME_CLOCK_FREQ_HZ 19200000
|
||||
#define CNSS_RAMDUMP_MAGIC 0x574C414E
|
||||
#define CNSS_RAMDUMP_VERSION 0
|
||||
#define MAX_FIRMWARE_NAME_LEN 40
|
||||
#define FW_V1_NUMBER 1
|
||||
#define FW_V2_NUMBER 2
|
||||
#ifdef CONFIG_CNSS_SUPPORT_DUAL_DEV
|
||||
#define POWER_ON_RETRY_MAX_TIMES 2
|
||||
#else
|
||||
#define POWER_ON_RETRY_MAX_TIMES 4
|
||||
#endif
|
||||
#define POWER_ON_RETRY_DELAY_MS 500
|
||||
#define CNSS_FS_NAME "cnss"
|
||||
#define CNSS_FS_NAME_SIZE 15
|
||||
#define CNSS_DEVICE_NAME_SIZE 16
|
||||
#define QRTR_NODE_FW_ID_BASE 7
|
||||
|
||||
#define POWER_ON_RETRY_DELAY_MS 500
|
||||
#define WLFW_MAX_HANG_EVENT_DATA_SIZE 384
|
||||
|
||||
#define CNSS_EVENT_SYNC BIT(0)
|
||||
#define CNSS_EVENT_UNINTERRUPTIBLE BIT(1)
|
||||
#define CNSS_EVENT_UNKILLABLE BIT(2)
|
||||
#define CNSS_EVENT_SYNC_UNINTERRUPTIBLE (CNSS_EVENT_SYNC | \
|
||||
CNSS_EVENT_UNINTERRUPTIBLE)
|
||||
#define CNSS_EVENT_SYNC_UNKILLABLE (CNSS_EVENT_SYNC | CNSS_EVENT_UNKILLABLE)
|
||||
#define QMI_WLFW_MAX_TME_OPT_FILE_NUM 3
|
||||
#define TME_OEM_FUSE_FILE_NAME "peach_sec.dat"
|
||||
#define TME_RPR_FILE_NAME "peach_rpr.bin"
|
||||
#define TME_DPR_FILE_NAME "peach_dpr.bin"
|
||||
|
||||
enum cnss_dt_type {
|
||||
CNSS_DTT_LEGACY = 0,
|
||||
CNSS_DTT_CONVERGED = 1,
|
||||
CNSS_DTT_MULTIEXCHG = 2
|
||||
};
|
||||
|
||||
enum cnss_dev_bus_type {
|
||||
CNSS_BUS_NONE = -1,
|
||||
CNSS_BUS_PCI,
|
||||
CNSS_BUS_MAX
|
||||
};
|
||||
|
||||
struct cnss_vreg_cfg {
|
||||
const char *name;
|
||||
u32 min_uv;
|
||||
u32 max_uv;
|
||||
u32 load_ua;
|
||||
u32 delay_us;
|
||||
u32 need_unvote;
|
||||
};
|
||||
|
||||
struct cnss_vreg_info {
|
||||
struct list_head list;
|
||||
struct regulator *reg;
|
||||
struct cnss_vreg_cfg cfg;
|
||||
u32 enabled;
|
||||
};
|
||||
|
||||
enum cnss_vreg_type {
|
||||
CNSS_VREG_PRIM,
|
||||
};
|
||||
|
||||
enum cnss_pci_switch_type {
|
||||
PCIE_DIRECT_ATTACH = 0,
|
||||
PCIE_SWITCH_NTN3,
|
||||
};
|
||||
|
||||
struct cnss_clk_cfg {
|
||||
const char *name;
|
||||
u32 freq;
|
||||
u32 required;
|
||||
};
|
||||
|
||||
struct cnss_clk_info {
|
||||
struct list_head list;
|
||||
struct clk *clk;
|
||||
struct cnss_clk_cfg cfg;
|
||||
u32 enabled;
|
||||
};
|
||||
|
||||
struct cnss_pinctrl_info {
|
||||
struct pinctrl *pinctrl;
|
||||
struct pinctrl_state *bootstrap_active;
|
||||
struct pinctrl_state *sol_default;
|
||||
struct pinctrl_state *wlan_en_active;
|
||||
struct pinctrl_state *wlan_en_sleep;
|
||||
struct pinctrl_state *sw_ctrl;
|
||||
struct pinctrl_state *sw_ctrl_wl_cx;
|
||||
int bt_en_gpio;
|
||||
int wlan_en_gpio;
|
||||
int xo_clk_gpio; /*qca6490 only */
|
||||
int sw_ctrl_gpio;
|
||||
int wlan_sw_ctrl_gpio;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
|
||||
struct cnss_subsys_info {
|
||||
struct subsys_device *subsys_device;
|
||||
struct subsys_desc subsys_desc;
|
||||
void *subsys_handle;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct cnss_ramdump_info {
|
||||
void *ramdump_dev;
|
||||
unsigned long ramdump_size;
|
||||
void *ramdump_va;
|
||||
phys_addr_t ramdump_pa;
|
||||
#if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2)
|
||||
struct msm_dump_data dump_data;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct cnss_dump_seg {
|
||||
unsigned long address;
|
||||
void *v_address;
|
||||
unsigned long size;
|
||||
u32 type;
|
||||
};
|
||||
|
||||
struct cnss_dump_data {
|
||||
u32 version;
|
||||
u32 magic;
|
||||
char name[32];
|
||||
phys_addr_t paddr;
|
||||
int nentries;
|
||||
u32 seg_version;
|
||||
};
|
||||
|
||||
struct cnss_ramdump_info_v2 {
|
||||
void *ramdump_dev;
|
||||
unsigned long ramdump_size;
|
||||
void *dump_data_vaddr;
|
||||
u8 dump_data_valid;
|
||||
struct cnss_dump_data dump_data;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ESOC)
|
||||
struct cnss_esoc_info {
|
||||
struct esoc_desc *esoc_desc;
|
||||
u8 notify_modem_status;
|
||||
void *modem_notify_handler;
|
||||
int modem_current_status;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_INTERCONNECT)
|
||||
/**
|
||||
* struct cnss_bus_bw_cfg - Interconnect vote data
|
||||
* @avg_bw: Vote for average bandwidth
|
||||
* @peak_bw: Vote for peak bandwidth
|
||||
*/
|
||||
struct cnss_bus_bw_cfg {
|
||||
u32 avg_bw;
|
||||
u32 peak_bw;
|
||||
};
|
||||
|
||||
/* Number of bw votes (avg, peak) entries that ICC requires */
|
||||
#define CNSS_ICC_VOTE_MAX 2
|
||||
|
||||
/**
|
||||
* struct cnss_bus_bw_info - Bus bandwidth config for interconnect path
|
||||
* @list: Kernel linked list
|
||||
* @icc_name: Name of interconnect path as defined in Device tree
|
||||
* @icc_path: Interconnect path data structure
|
||||
* @cfg_table: Interconnect vote data for average and peak bandwidth
|
||||
*/
|
||||
struct cnss_bus_bw_info {
|
||||
struct list_head list;
|
||||
const char *icc_name;
|
||||
struct icc_path *icc_path;
|
||||
struct cnss_bus_bw_cfg *cfg_table;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct cnss_interconnect_cfg - CNSS platform interconnect config
|
||||
* @list_head: List of interconnect path bandwidth configs
|
||||
* @path_count: Count of interconnect path configured in device tree
|
||||
* @current_bw_vote: WLAN driver provided bandwidth vote
|
||||
* @bus_bw_cfg_count: Number of bandwidth configs for voting. It is the array
|
||||
* size of struct cnss_bus_bw_info.cfg_table
|
||||
*/
|
||||
struct cnss_interconnect_cfg {
|
||||
struct list_head list_head;
|
||||
u32 path_count;
|
||||
int current_bw_vote;
|
||||
u32 bus_bw_cfg_count;
|
||||
};
|
||||
|
||||
struct cnss_fw_mem {
|
||||
size_t size;
|
||||
void *va;
|
||||
phys_addr_t pa;
|
||||
u8 valid;
|
||||
u32 type;
|
||||
unsigned long attrs;
|
||||
};
|
||||
|
||||
struct wlfw_rf_chip_info {
|
||||
u32 chip_id;
|
||||
u32 chip_family;
|
||||
};
|
||||
|
||||
struct wlfw_rf_board_info {
|
||||
u32 board_id;
|
||||
};
|
||||
|
||||
struct wlfw_soc_info {
|
||||
u32 soc_id;
|
||||
};
|
||||
|
||||
struct wlfw_fw_version_info {
|
||||
u32 fw_version;
|
||||
char fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN + 1];
|
||||
};
|
||||
|
||||
enum cnss_mem_type {
|
||||
CNSS_MEM_TYPE_MSA,
|
||||
CNSS_MEM_TYPE_DDR,
|
||||
CNSS_MEM_BDF,
|
||||
CNSS_MEM_M3,
|
||||
CNSS_MEM_CAL_V01,
|
||||
CNSS_MEM_DPD_V01,
|
||||
CNSS_MEM_AUX,
|
||||
};
|
||||
|
||||
enum cnss_fw_dump_type {
|
||||
CNSS_FW_IMAGE,
|
||||
CNSS_FW_RDDM,
|
||||
CNSS_FW_REMOTE_HEAP,
|
||||
CNSS_FW_CAL,
|
||||
CNSS_FW_DUMP_TYPE_MAX,
|
||||
};
|
||||
|
||||
struct cnss_dump_entry {
|
||||
int type;
|
||||
u32 entry_start;
|
||||
u32 entry_num;
|
||||
};
|
||||
|
||||
struct cnss_dump_meta_info {
|
||||
u32 magic;
|
||||
u32 version;
|
||||
u32 chipset;
|
||||
u32 total_entries;
|
||||
struct cnss_dump_entry entry[CNSS_FW_DUMP_TYPE_MAX];
|
||||
};
|
||||
|
||||
struct cnss_host_dump_meta_info {
|
||||
u32 magic;
|
||||
u32 version;
|
||||
u32 chipset;
|
||||
u32 total_entries;
|
||||
struct cnss_dump_entry entry[CNSS_HOST_DUMP_TYPE_MAX];
|
||||
};
|
||||
|
||||
enum cnss_driver_event_type {
|
||||
CNSS_DRIVER_EVENT_SERVER_ARRIVE,
|
||||
CNSS_DRIVER_EVENT_SERVER_EXIT,
|
||||
CNSS_DRIVER_EVENT_REQUEST_MEM,
|
||||
CNSS_DRIVER_EVENT_FW_MEM_READY,
|
||||
CNSS_DRIVER_EVENT_FW_READY,
|
||||
CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START,
|
||||
CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE,
|
||||
CNSS_DRIVER_EVENT_REGISTER_DRIVER,
|
||||
CNSS_DRIVER_EVENT_UNREGISTER_DRIVER,
|
||||
CNSS_DRIVER_EVENT_RECOVERY,
|
||||
CNSS_DRIVER_EVENT_FORCE_FW_ASSERT,
|
||||
CNSS_DRIVER_EVENT_POWER_UP,
|
||||
CNSS_DRIVER_EVENT_POWER_DOWN,
|
||||
CNSS_DRIVER_EVENT_IDLE_RESTART,
|
||||
CNSS_DRIVER_EVENT_IDLE_SHUTDOWN,
|
||||
CNSS_DRIVER_EVENT_IMS_WFC_CALL_IND,
|
||||
CNSS_DRIVER_EVENT_WLFW_TWT_CFG_IND,
|
||||
CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM,
|
||||
CNSS_DRIVER_EVENT_FW_MEM_FILE_SAVE,
|
||||
CNSS_DRIVER_EVENT_QDSS_TRACE_FREE,
|
||||
CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_DATA,
|
||||
CNSS_DRIVER_EVENT_MAX,
|
||||
};
|
||||
|
||||
enum cnss_driver_state {
|
||||
CNSS_QMI_WLFW_CONNECTED = 0,
|
||||
CNSS_FW_MEM_READY,
|
||||
CNSS_FW_READY,
|
||||
CNSS_IN_COLD_BOOT_CAL,
|
||||
CNSS_DRIVER_LOADING,
|
||||
CNSS_DRIVER_UNLOADING = 5,
|
||||
CNSS_DRIVER_IDLE_RESTART,
|
||||
CNSS_DRIVER_IDLE_SHUTDOWN,
|
||||
CNSS_DRIVER_PROBED,
|
||||
CNSS_DRIVER_RECOVERY,
|
||||
CNSS_FW_BOOT_RECOVERY = 10,
|
||||
CNSS_DEV_ERR_NOTIFY,
|
||||
CNSS_DRIVER_DEBUG,
|
||||
CNSS_COEX_CONNECTED,
|
||||
CNSS_IMS_CONNECTED,
|
||||
CNSS_IN_SUSPEND_RESUME = 15,
|
||||
CNSS_IN_REBOOT,
|
||||
CNSS_COLD_BOOT_CAL_DONE,
|
||||
CNSS_IN_PANIC,
|
||||
CNSS_QMI_DEL_SERVER,
|
||||
CNSS_QMI_DMS_CONNECTED = 20,
|
||||
CNSS_DAEMON_CONNECTED,
|
||||
CNSS_PCI_PROBE_DONE,
|
||||
CNSS_DRIVER_REGISTER,
|
||||
CNSS_WLAN_HW_DISABLED,
|
||||
CNSS_FS_READY = 25,
|
||||
CNSS_DRIVER_REGISTERED,
|
||||
CNSS_DMS_DEL_SERVER,
|
||||
CNSS_POWER_OFF,
|
||||
};
|
||||
|
||||
struct cnss_recovery_data {
|
||||
enum cnss_recovery_reason reason;
|
||||
};
|
||||
|
||||
enum cnss_pins {
|
||||
CNSS_WLAN_EN,
|
||||
CNSS_PCIE_TXP,
|
||||
CNSS_PCIE_TXN,
|
||||
CNSS_PCIE_RXP,
|
||||
CNSS_PCIE_RXN,
|
||||
CNSS_PCIE_REFCLKP,
|
||||
CNSS_PCIE_REFCLKN,
|
||||
CNSS_PCIE_RST,
|
||||
CNSS_PCIE_WAKE,
|
||||
};
|
||||
|
||||
struct cnss_pin_connect_result {
|
||||
u32 fw_pwr_pin_result;
|
||||
u32 fw_phy_io_pin_result;
|
||||
u32 fw_rf_pin_result;
|
||||
u32 host_pin_result;
|
||||
};
|
||||
|
||||
enum cnss_debug_quirks {
|
||||
LINK_DOWN_SELF_RECOVERY,
|
||||
SKIP_DEVICE_BOOT,
|
||||
USE_CORE_ONLY_FW,
|
||||
SKIP_RECOVERY,
|
||||
QMI_BYPASS,
|
||||
ENABLE_WALTEST,
|
||||
ENABLE_PCI_LINK_DOWN_PANIC,
|
||||
FBC_BYPASS,
|
||||
ENABLE_DAEMON_SUPPORT,
|
||||
DISABLE_DRV,
|
||||
DISABLE_IO_COHERENCY,
|
||||
IGNORE_PCI_LINK_FAILURE,
|
||||
DISABLE_TIME_SYNC,
|
||||
FORCE_ONE_MSI,
|
||||
QUIRK_MAX_VALUE
|
||||
};
|
||||
|
||||
enum cnss_bdf_type {
|
||||
CNSS_BDF_BIN,
|
||||
CNSS_BDF_ELF,
|
||||
CNSS_BDF_REGDB = 4,
|
||||
CNSS_BDF_HDS = 6,
|
||||
};
|
||||
|
||||
enum cnss_cal_status {
|
||||
CNSS_CAL_DONE,
|
||||
CNSS_CAL_TIMEOUT,
|
||||
CNSS_CAL_FAILURE,
|
||||
};
|
||||
|
||||
struct cnss_cal_info {
|
||||
enum cnss_cal_status cal_status;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cnss_time_sync_period_vote - to get per vote time sync period
|
||||
* @TIME_SYNC_VOTE_WLAN: WLAN Driver vote
|
||||
* @TIME_SYNC_VOTE_CNSS: sys config vote
|
||||
* @TIME_SYNC_VOTE_MAX
|
||||
*/
|
||||
enum cnss_time_sync_period_vote {
|
||||
TIME_SYNC_VOTE_WLAN,
|
||||
TIME_SYNC_VOTE_CNSS,
|
||||
TIME_SYNC_VOTE_MAX,
|
||||
};
|
||||
|
||||
struct cnss_control_params {
|
||||
unsigned long quirks;
|
||||
unsigned int mhi_timeout;
|
||||
unsigned int mhi_m2_timeout;
|
||||
unsigned int qmi_timeout;
|
||||
unsigned int bdf_type;
|
||||
unsigned int time_sync_period;
|
||||
unsigned int time_sync_period_vote[TIME_SYNC_VOTE_MAX];
|
||||
};
|
||||
|
||||
struct cnss_tcs_info {
|
||||
resource_size_t cmd_base_addr;
|
||||
void __iomem *cmd_base_addr_io;
|
||||
};
|
||||
|
||||
struct cnss_cpr_info {
|
||||
resource_size_t tcs_cmd_data_addr;
|
||||
void __iomem *tcs_cmd_data_addr_io;
|
||||
u32 cpr_pmic_addr;
|
||||
u32 voltage;
|
||||
};
|
||||
|
||||
enum cnss_ce_index {
|
||||
CNSS_CE_00,
|
||||
CNSS_CE_01,
|
||||
CNSS_CE_02,
|
||||
CNSS_CE_03,
|
||||
CNSS_CE_04,
|
||||
CNSS_CE_05,
|
||||
CNSS_CE_06,
|
||||
CNSS_CE_07,
|
||||
CNSS_CE_08,
|
||||
CNSS_CE_09,
|
||||
CNSS_CE_10,
|
||||
CNSS_CE_11,
|
||||
CNSS_CE_COMMON,
|
||||
};
|
||||
|
||||
struct cnss_dms_data {
|
||||
u32 mac_valid;
|
||||
u8 mac[QMI_WLFW_MAC_ADDR_SIZE_V01];
|
||||
};
|
||||
|
||||
enum cnss_timeout_type {
|
||||
CNSS_TIMEOUT_QMI,
|
||||
CNSS_TIMEOUT_POWER_UP,
|
||||
CNSS_TIMEOUT_IDLE_RESTART,
|
||||
CNSS_TIMEOUT_CALIBRATION,
|
||||
CNSS_TIMEOUT_WLAN_WATCHDOG,
|
||||
CNSS_TIMEOUT_RDDM,
|
||||
CNSS_TIMEOUT_RECOVERY,
|
||||
CNSS_TIMEOUT_DAEMON_CONNECTION,
|
||||
};
|
||||
|
||||
struct cnss_sol_gpio {
|
||||
int dev_sol_gpio;
|
||||
int dev_sol_irq;
|
||||
u32 dev_sol_counter;
|
||||
int host_sol_gpio;
|
||||
};
|
||||
|
||||
struct cnss_thermal_cdev {
|
||||
struct list_head tcdev_list;
|
||||
int tcdev_id;
|
||||
unsigned long curr_thermal_state;
|
||||
unsigned long max_thermal_state;
|
||||
struct device_node *dev_node;
|
||||
struct thermal_cooling_device *tcdev;
|
||||
};
|
||||
|
||||
struct cnss_plat_data {
|
||||
struct platform_device *plat_dev;
|
||||
enum cnss_driver_mode driver_mode;
|
||||
void *bus_priv;
|
||||
enum cnss_dev_bus_type bus_type;
|
||||
struct list_head vreg_list;
|
||||
struct list_head clk_list;
|
||||
struct cnss_pinctrl_info pinctrl_info;
|
||||
struct cnss_sol_gpio sol_gpio;
|
||||
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
|
||||
struct cnss_subsys_info subsys_info;
|
||||
#endif
|
||||
struct cnss_ramdump_info ramdump_info;
|
||||
struct cnss_ramdump_info_v2 ramdump_info_v2;
|
||||
#if IS_ENABLED(CONFIG_ESOC)
|
||||
struct cnss_esoc_info esoc_info;
|
||||
#endif
|
||||
struct cnss_interconnect_cfg icc;
|
||||
struct notifier_block modem_nb;
|
||||
struct notifier_block reboot_nb;
|
||||
struct notifier_block panic_nb;
|
||||
struct cnss_platform_cap cap;
|
||||
struct pm_qos_request qos_request;
|
||||
struct cnss_device_version device_version;
|
||||
u32 rc_num;
|
||||
unsigned long device_id;
|
||||
enum cnss_driver_status driver_status;
|
||||
u32 recovery_count;
|
||||
u8 recovery_enabled;
|
||||
u8 recovery_pcss_enabled;
|
||||
u8 hds_enabled;
|
||||
unsigned long driver_state;
|
||||
struct list_head event_list;
|
||||
struct list_head cnss_tcdev_list;
|
||||
struct mutex tcdev_lock; /* mutex for cooling devices list access */
|
||||
spinlock_t event_lock; /* spinlock for driver work event handling */
|
||||
struct work_struct event_work;
|
||||
struct workqueue_struct *event_wq;
|
||||
struct work_struct recovery_work;
|
||||
struct delayed_work wlan_reg_driver_work;
|
||||
struct qmi_handle qmi_wlfw;
|
||||
struct qmi_handle qmi_dms;
|
||||
struct wlfw_rf_chip_info chip_info;
|
||||
struct wlfw_rf_board_info board_info;
|
||||
struct wlfw_soc_info soc_info;
|
||||
struct wlfw_fw_version_info fw_version_info;
|
||||
struct cnss_dev_mem_info dev_mem_info[CNSS_MAX_DEV_MEM_NUM];
|
||||
char fw_build_id[QMI_WLFW_MAX_BUILD_ID_LEN + 1];
|
||||
u32 otp_version;
|
||||
u32 fw_mem_seg_len;
|
||||
struct cnss_fw_mem fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
|
||||
struct cnss_fw_mem m3_mem;
|
||||
struct cnss_fw_mem tme_lite_mem;
|
||||
struct cnss_fw_mem tme_opt_file_mem[QMI_WLFW_MAX_TME_OPT_FILE_NUM];
|
||||
struct cnss_fw_mem *cal_mem;
|
||||
struct cnss_fw_mem aux_mem;
|
||||
u64 cal_time;
|
||||
bool cbc_file_download;
|
||||
u32 cal_file_size;
|
||||
struct completion daemon_connected;
|
||||
u32 qdss_mem_seg_len;
|
||||
struct cnss_fw_mem qdss_mem[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
|
||||
u32 *qdss_reg;
|
||||
struct cnss_pin_connect_result pin_result;
|
||||
struct dentry *root_dentry;
|
||||
atomic_t pm_count;
|
||||
struct timer_list fw_boot_timer;
|
||||
struct completion power_up_complete;
|
||||
struct completion cal_complete;
|
||||
struct mutex dev_lock; /* mutex for register access through debugfs */
|
||||
struct mutex driver_ops_lock; /* mutex for external driver ops */
|
||||
struct cnss_wlan_driver *driver_ops;
|
||||
u32 supported_link_speed;
|
||||
u32 device_freq_hz;
|
||||
u32 diag_reg_read_addr;
|
||||
u32 diag_reg_read_mem_type;
|
||||
u32 diag_reg_read_len;
|
||||
u8 *diag_reg_read_buf;
|
||||
u8 cal_done;
|
||||
u8 powered_on;
|
||||
u8 use_fw_path_with_prefix;
|
||||
char firmware_name[MAX_FIRMWARE_NAME_LEN];
|
||||
char fw_fallback_name[MAX_FIRMWARE_NAME_LEN];
|
||||
#ifndef CONFIG_DISABLE_CNSS_SRAM_DUMP
|
||||
u8 *sram_dump;
|
||||
#endif
|
||||
struct completion rddm_complete;
|
||||
struct completion recovery_complete;
|
||||
struct cnss_control_params ctrl_params;
|
||||
struct cnss_cpr_info cpr_info;
|
||||
u64 antenna;
|
||||
u64 grant;
|
||||
struct qmi_handle coex_qmi;
|
||||
struct qmi_handle ims_qmi;
|
||||
struct qmi_txn txn;
|
||||
struct wakeup_source *recovery_ws;
|
||||
u64 dynamic_feature;
|
||||
void *get_info_cb_ctx;
|
||||
int (*get_info_cb)(void *ctx, void *event, int event_len);
|
||||
void *get_driver_async_data_ctx;
|
||||
int (*get_driver_async_data_cb)(void *ctx, uint16_t type, void *event, int event_len);
|
||||
bool cbc_enabled;
|
||||
u8 use_pm_domain;
|
||||
u8 use_nv_mac;
|
||||
u8 set_wlaon_pwr_ctrl;
|
||||
struct cnss_tcs_info tcs_info;
|
||||
bool fw_pcie_gen_switch;
|
||||
bool fw_aux_uc_support;
|
||||
u64 fw_caps;
|
||||
u8 pcie_gen_speed;
|
||||
struct iommu_domain *audio_iommu_domain;
|
||||
bool is_audio_shared_iommu_group;
|
||||
struct cnss_dms_data dms;
|
||||
int power_up_error;
|
||||
u32 hw_trc_override;
|
||||
u8 charger_mode;
|
||||
struct mbox_client mbox_client_data;
|
||||
struct mbox_chan *mbox_chan;
|
||||
struct qmp *qmp;
|
||||
const char *vreg_ol_cpr, *vreg_ipa;
|
||||
const char **pdc_init_table, **vreg_pdc_map, **pmu_vreg_map;
|
||||
int pdc_init_table_len, vreg_pdc_map_len, pmu_vreg_map_len;
|
||||
bool adsp_pc_enabled;
|
||||
u64 feature_list;
|
||||
u32 dt_type;
|
||||
struct kobject *wifi_kobj;
|
||||
u16 hang_event_data_len;
|
||||
u32 hang_data_addr_offset;
|
||||
/* bitmap to detect FEM combination */
|
||||
u8 hwid_bitmap;
|
||||
uint32_t num_shadow_regs_v3;
|
||||
bool sec_peri_feature_disable;
|
||||
struct device_node *dev_node;
|
||||
char device_name[CNSS_DEVICE_NAME_SIZE];
|
||||
u32 plat_idx;
|
||||
bool enumerate_done;
|
||||
int qrtr_node_id;
|
||||
unsigned int wlfw_service_instance_id;
|
||||
const char *pld_bus_ops_name;
|
||||
u32 on_chip_pmic_devices_count;
|
||||
u32 *on_chip_pmic_board_ids;
|
||||
bool no_bwscale;
|
||||
bool sleep_clk;
|
||||
struct wlchip_serial_id_v01 serial_id;
|
||||
bool ipa_shared_cb_enable;
|
||||
u32 pcie_switch_type;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ARCH_QCOM)
|
||||
static inline u64 cnss_get_host_timestamp(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
u64 ticks = __arch_counter_get_cntvct();
|
||||
|
||||
do_div(ticks, TIME_CLOCK_FREQ_HZ / 100000);
|
||||
|
||||
return ticks * 10;
|
||||
}
|
||||
#else
|
||||
static inline u64 cnss_get_host_timestamp(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
struct timespec64 ts;
|
||||
|
||||
ktime_get_ts64(&ts);
|
||||
|
||||
return (ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
int cnss_wlan_hw_disable_check(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlan_hw_enable(void);
|
||||
struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev);
|
||||
struct cnss_plat_data *cnss_get_first_plat_priv(struct platform_device *plat_dev);
|
||||
void cnss_pm_stay_awake(struct cnss_plat_data *plat_priv);
|
||||
void cnss_pm_relax(struct cnss_plat_data *plat_priv);
|
||||
struct cnss_plat_data *cnss_get_plat_priv_by_rc_num(int rc_num);
|
||||
int cnss_get_max_plat_env_count(void);
|
||||
struct cnss_plat_data *cnss_get_plat_env(int index);
|
||||
void cnss_get_qrtr_info(struct cnss_plat_data *plat_priv);
|
||||
void cnss_get_sleep_clk_supported(struct cnss_plat_data *plat_priv);
|
||||
void cnss_get_bwscal_info(struct cnss_plat_data *plat_priv);
|
||||
bool cnss_is_dual_wlan_enabled(void);
|
||||
int cnss_driver_event_post(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_driver_event_type type,
|
||||
u32 flags, void *data);
|
||||
int cnss_get_vreg_type(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_vreg_type type);
|
||||
void cnss_put_vreg_type(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_vreg_type type);
|
||||
int cnss_vreg_on_type(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_vreg_type type);
|
||||
int cnss_vreg_off_type(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_vreg_type type);
|
||||
int cnss_get_clk(struct cnss_plat_data *plat_priv);
|
||||
void cnss_put_clk(struct cnss_plat_data *plat_priv);
|
||||
int cnss_vreg_unvote_type(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_vreg_type type);
|
||||
int cnss_get_pinctrl(struct cnss_plat_data *plat_priv);
|
||||
int cnss_get_wlan_sw_ctrl(struct cnss_plat_data *plat_priv);
|
||||
int cnss_power_on_device(struct cnss_plat_data *plat_priv, bool reset);
|
||||
void cnss_power_off_device(struct cnss_plat_data *plat_priv);
|
||||
bool cnss_is_device_powered_on(struct cnss_plat_data *plat_priv);
|
||||
int cnss_enable_dev_sol_irq(struct cnss_plat_data *plat_priv);
|
||||
int cnss_disable_dev_sol_irq(struct cnss_plat_data *plat_priv);
|
||||
int cnss_get_dev_sol_value(struct cnss_plat_data *plat_priv);
|
||||
int cnss_init_dev_sol_irq(struct cnss_plat_data *plat_priv);
|
||||
int cnss_deinit_dev_sol_irq(struct cnss_plat_data *plat_priv);
|
||||
int cnss_set_host_sol_value(struct cnss_plat_data *plat_priv, int value);
|
||||
int cnss_get_host_sol_value(struct cnss_plat_data *plat_priv);
|
||||
int cnss_register_subsys(struct cnss_plat_data *plat_priv);
|
||||
void cnss_unregister_subsys(struct cnss_plat_data *plat_priv);
|
||||
int cnss_register_ramdump(struct cnss_plat_data *plat_priv);
|
||||
void cnss_unregister_ramdump(struct cnss_plat_data *plat_priv);
|
||||
int cnss_do_ramdump(struct cnss_plat_data *plat_priv);
|
||||
int cnss_do_elf_ramdump(struct cnss_plat_data *plat_priv);
|
||||
int cnss_do_host_ramdump(struct cnss_plat_data *plat_priv,
|
||||
struct cnss_ssr_driver_dump_entry *ssr_entry,
|
||||
size_t num_entries_loaded);
|
||||
void cnss_set_pin_connect_status(struct cnss_plat_data *plat_priv);
|
||||
int cnss_get_cpr_info(struct cnss_plat_data *plat_priv);
|
||||
int cnss_update_cpr_info(struct cnss_plat_data *plat_priv);
|
||||
int cnss_va_to_pa(struct device *dev, size_t size, void *va, dma_addr_t dma,
|
||||
phys_addr_t *pa, unsigned long attrs);
|
||||
int cnss_minidump_add_region(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_fw_dump_type type, int seg_no,
|
||||
void *va, phys_addr_t pa, size_t size);
|
||||
int cnss_minidump_remove_region(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_fw_dump_type type, int seg_no,
|
||||
void *va, phys_addr_t pa, size_t size);
|
||||
int cnss_enable_int_pow_amp_vreg(struct cnss_plat_data *plat_priv);
|
||||
int cnss_get_tcs_info(struct cnss_plat_data *plat_priv);
|
||||
unsigned int cnss_get_timeout(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_timeout_type);
|
||||
int cnss_aop_interface_init(struct cnss_plat_data *plat_priv);
|
||||
void cnss_aop_interface_deinit(struct cnss_plat_data *plat_priv);
|
||||
int cnss_aop_pdc_reconfig(struct cnss_plat_data *plat_priv);
|
||||
int cnss_aop_send_msg(struct cnss_plat_data *plat_priv, char *msg);
|
||||
void cnss_power_misc_params_init(struct cnss_plat_data *plat_priv);
|
||||
void cnss_pci_of_switch_type_init(struct cnss_plat_data *plat_priv);
|
||||
int cnss_aop_ol_cpr_cfg_setup(struct cnss_plat_data *plat_priv,
|
||||
struct wlfw_pmu_cfg_v01 *fw_pmu_cfg);
|
||||
int cnss_request_firmware_direct(struct cnss_plat_data *plat_priv,
|
||||
const struct firmware **fw_entry,
|
||||
const char *filename);
|
||||
int cnss_set_feature_list(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_feature_v01 feature);
|
||||
int cnss_clear_feature_list(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_feature_v01 feature);
|
||||
int cnss_get_feature_list(struct cnss_plat_data *plat_priv,
|
||||
u64 *feature_list);
|
||||
int cnss_get_input_gpio_value(struct cnss_plat_data *plat_priv, int gpio_num);
|
||||
bool cnss_check_driver_loading_allowed(void);
|
||||
int cnss_dev_specific_power_on(struct cnss_plat_data *plat_priv);
|
||||
void cnss_recovery_handler(struct cnss_plat_data *plat_priv);
|
||||
size_t cnss_get_platform_name(struct cnss_plat_data *plat_priv,
|
||||
char *buf, const size_t buf_len);
|
||||
int cnss_iommu_map(struct iommu_domain *domain, unsigned long iova,
|
||||
phys_addr_t paddr, size_t size, int prot);
|
||||
int cnss_select_pinctrl_enable(struct cnss_plat_data *plat_priv);
|
||||
int cnss_select_pinctrl_state(struct cnss_plat_data *plat_priv, bool state);
|
||||
#endif /* _CNSS_MAIN_H */
|
@@ -0,0 +1,12 @@
|
||||
CONFIG_CNSS2=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
||||
CONFIG_CNSS2_QMI=y
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_BUS_AUTO_SUSPEND=y
|
||||
CONFIG_CNSS2_SSR_DRIVER_DUMP=y
|
||||
CONFIG_CNSS_HW_SECURE_DISABLE=y
|
||||
CONFIG_CNSS_HW_SECURE_SMEM=y
|
||||
CONFIG_CNSS2_SMMU_DB_SUPPORT=y
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS2_DEBUG=y
|
@@ -0,0 +1,11 @@
|
||||
CONFIG_CNSS2=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
||||
CONFIG_CNSS2_QMI=y
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_BUS_AUTO_SUSPEND=y
|
||||
CONFIG_CNSS2_SSR_DRIVER_DUMP=y
|
||||
CONFIG_CNSS_HW_SECURE_DISABLE=y
|
||||
CONFIG_CNSS_HW_SECURE_SMEM=y
|
||||
CONFIG_CNSS2_SMMU_DB_SUPPORT=y
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
文件差异内容过多而无法显示
加载差异
@@ -0,0 +1,350 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CNSS_PCI_H
|
||||
#define _CNSS_PCI_H
|
||||
|
||||
#include <linux/cma.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/qcom-iommu-util.h>
|
||||
#include <linux/mhi.h>
|
||||
#if IS_ENABLED(CONFIG_MHI_BUS_MISC)
|
||||
#include <linux/mhi_misc.h>
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_PCI_MSM)
|
||||
#include <linux/msm_pcie.h>
|
||||
#endif
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/sched_clock.h>
|
||||
#include <linux/version.h>
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 2, 0))
|
||||
#include <linux/sched/clock.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#define PM_OPTIONS_DEFAULT 0
|
||||
#define PCI_LINK_DOWN 0
|
||||
|
||||
#ifdef CONFIG_CNSS_SUPPORT_DUAL_DEV
|
||||
#define LINK_TRAINING_RETRY_MAX_TIMES 2
|
||||
#else
|
||||
#define LINK_TRAINING_RETRY_MAX_TIMES 3
|
||||
#endif
|
||||
|
||||
#define LINK_TRAINING_RETRY_DELAY_MS 500
|
||||
#define MSI_USERS 4
|
||||
|
||||
#define CNSS_MHI_IN_MISSION_MODE(ee) (ee == MHI_EE_AMSS || \
|
||||
ee == MHI_EE_WFW || \
|
||||
ee == MHI_EE_FP)
|
||||
|
||||
#define PCI_DSP_LINK_ENABLE 1
|
||||
#define PCI_DSP_LINK_DISABLE 0
|
||||
#ifdef CONFIG_PCIE_SWITCH_SUPPORT
|
||||
#define DSP_LINK_ENABLE_DELAY_TIME_US_MIN (25000)
|
||||
#define DSP_LINK_ENABLE_DELAY_TIME_US_MAX (25100)
|
||||
#define DSP_LINK_ENABLE_RETRY_COUNT_MAX (3)
|
||||
#endif
|
||||
|
||||
enum cnss_mhi_state {
|
||||
CNSS_MHI_INIT,
|
||||
CNSS_MHI_DEINIT,
|
||||
CNSS_MHI_POWER_ON,
|
||||
CNSS_MHI_POWERING_OFF,
|
||||
CNSS_MHI_POWER_OFF,
|
||||
CNSS_MHI_FORCE_POWER_OFF,
|
||||
CNSS_MHI_SUSPEND,
|
||||
CNSS_MHI_RESUME,
|
||||
CNSS_MHI_TRIGGER_RDDM,
|
||||
CNSS_MHI_RDDM,
|
||||
CNSS_MHI_RDDM_DONE,
|
||||
};
|
||||
|
||||
enum pci_link_status {
|
||||
PCI_GEN1,
|
||||
PCI_GEN2,
|
||||
PCI_DEF,
|
||||
};
|
||||
|
||||
enum cnss_rtpm_id {
|
||||
RTPM_ID_CNSS,
|
||||
RTPM_ID_MHI,
|
||||
RTPM_ID_MAX,
|
||||
};
|
||||
|
||||
enum cnss_pci_reg_dev_mask {
|
||||
REG_MASK_QCA6390,
|
||||
REG_MASK_QCA6490,
|
||||
REG_MASK_KIWI,
|
||||
REG_MASK_MANGO,
|
||||
REG_MASK_PEACH,
|
||||
};
|
||||
|
||||
enum cnss_smmu_fault_time {
|
||||
SMMU_CB_ENTRY,
|
||||
SMMU_CB_DOORBELL_RING,
|
||||
SMMU_CB_EXIT,
|
||||
SMMU_CB_MAX,
|
||||
};
|
||||
|
||||
struct cnss_msi_user {
|
||||
char *name;
|
||||
int num_vectors;
|
||||
u32 base_vector;
|
||||
};
|
||||
|
||||
struct cnss_msi_config {
|
||||
int total_vectors;
|
||||
int total_users;
|
||||
struct cnss_msi_user *users;
|
||||
};
|
||||
|
||||
struct cnss_pci_reg {
|
||||
char *name;
|
||||
u32 offset;
|
||||
};
|
||||
|
||||
struct cnss_pci_debug_reg {
|
||||
u32 offset;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
struct cnss_misc_reg {
|
||||
unsigned long dev_mask;
|
||||
u8 wr;
|
||||
u32 offset;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
struct cnss_pm_stats {
|
||||
atomic_t runtime_get;
|
||||
atomic_t runtime_put;
|
||||
atomic_t runtime_get_id[RTPM_ID_MAX];
|
||||
atomic_t runtime_put_id[RTPM_ID_MAX];
|
||||
u64 runtime_get_timestamp_id[RTPM_ID_MAX];
|
||||
u64 runtime_put_timestamp_id[RTPM_ID_MAX];
|
||||
};
|
||||
|
||||
struct cnss_print_optimize {
|
||||
int msi_log_chk[MSI_USERS];
|
||||
int msi_addr_chk;
|
||||
};
|
||||
|
||||
struct cnss_pci_data {
|
||||
struct pci_dev *pci_dev;
|
||||
struct cnss_plat_data *plat_priv;
|
||||
const struct pci_device_id *pci_device_id;
|
||||
u32 device_id;
|
||||
u16 revision_id;
|
||||
u64 dma_bit_mask;
|
||||
struct cnss_wlan_driver *driver_ops;
|
||||
u8 pci_link_state;
|
||||
u8 pci_link_down_ind;
|
||||
struct pci_saved_state *saved_state;
|
||||
struct pci_saved_state *default_state;
|
||||
#if IS_ENABLED(CONFIG_PCI_MSM)
|
||||
struct msm_pcie_register_event msm_pci_event;
|
||||
#endif
|
||||
struct cnss_pm_stats pm_stats;
|
||||
atomic_t auto_suspended;
|
||||
atomic_t drv_connected;
|
||||
u8 drv_connected_last;
|
||||
u32 qmi_send_usage_count;
|
||||
u16 def_link_speed;
|
||||
u16 def_link_width;
|
||||
u16 cur_link_speed;
|
||||
int wake_gpio;
|
||||
int wake_irq;
|
||||
u32 wake_counter;
|
||||
u8 monitor_wake_intr;
|
||||
struct iommu_domain *iommu_domain;
|
||||
u8 smmu_s1_enable;
|
||||
dma_addr_t smmu_iova_start;
|
||||
size_t smmu_iova_len;
|
||||
dma_addr_t smmu_iova_ipa_start;
|
||||
dma_addr_t smmu_iova_ipa_current;
|
||||
size_t smmu_iova_ipa_len;
|
||||
void __iomem *bar;
|
||||
struct cnss_msi_config *msi_config;
|
||||
u32 msi_ep_base_data;
|
||||
u32 msix_addr;
|
||||
struct mhi_controller *mhi_ctrl;
|
||||
unsigned long mhi_state;
|
||||
u32 remap_window;
|
||||
struct completion wake_event_complete;
|
||||
struct timer_list dev_rddm_timer;
|
||||
struct timer_list boot_debug_timer;
|
||||
struct delayed_work time_sync_work;
|
||||
u8 disable_pc;
|
||||
struct mutex bus_lock; /* mutex for suspend and resume bus */
|
||||
struct cnss_pci_debug_reg *debug_reg;
|
||||
struct cnss_misc_reg *wcss_reg;
|
||||
struct cnss_misc_reg *pcie_reg;
|
||||
struct cnss_misc_reg *wlaon_reg;
|
||||
struct cnss_misc_reg *syspm_reg;
|
||||
unsigned long misc_reg_dev_mask;
|
||||
u8 iommu_geometry;
|
||||
bool drv_supported;
|
||||
bool is_smmu_fault;
|
||||
unsigned long long smmu_fault_timestamp[SMMU_CB_MAX];
|
||||
#ifdef CONFIG_PCIE_SWITCH_SUPPORT
|
||||
bool pci_dsp_link_status;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline void cnss_set_pci_priv(struct pci_dev *pci_dev, void *data)
|
||||
{
|
||||
pci_set_drvdata(pci_dev, data);
|
||||
}
|
||||
|
||||
static inline struct cnss_pci_data *cnss_get_pci_priv(struct pci_dev *pci_dev)
|
||||
{
|
||||
return pci_get_drvdata(pci_dev);
|
||||
}
|
||||
|
||||
static inline struct cnss_plat_data *cnss_pci_priv_to_plat_priv(void *bus_priv)
|
||||
{
|
||||
struct cnss_pci_data *pci_priv = bus_priv;
|
||||
|
||||
return pci_priv->plat_priv;
|
||||
}
|
||||
|
||||
static inline void cnss_pci_set_monitor_wake_intr(void *bus_priv, bool val)
|
||||
{
|
||||
struct cnss_pci_data *pci_priv = bus_priv;
|
||||
|
||||
pci_priv->monitor_wake_intr = val;
|
||||
}
|
||||
|
||||
static inline bool cnss_pci_get_monitor_wake_intr(void *bus_priv)
|
||||
{
|
||||
struct cnss_pci_data *pci_priv = bus_priv;
|
||||
|
||||
return pci_priv->monitor_wake_intr;
|
||||
}
|
||||
|
||||
static inline void cnss_pci_set_auto_suspended(void *bus_priv, int val)
|
||||
{
|
||||
struct cnss_pci_data *pci_priv = bus_priv;
|
||||
|
||||
atomic_set(&pci_priv->auto_suspended, val);
|
||||
}
|
||||
|
||||
static inline int cnss_pci_get_auto_suspended(void *bus_priv)
|
||||
{
|
||||
struct cnss_pci_data *pci_priv = bus_priv;
|
||||
|
||||
return atomic_read(&pci_priv->auto_suspended);
|
||||
}
|
||||
|
||||
static inline void cnss_pci_set_drv_connected(void *bus_priv, int val)
|
||||
{
|
||||
struct cnss_pci_data *pci_priv = bus_priv;
|
||||
|
||||
atomic_set(&pci_priv->drv_connected, val);
|
||||
}
|
||||
|
||||
static inline int cnss_pci_get_drv_connected(void *bus_priv)
|
||||
{
|
||||
struct cnss_pci_data *pci_priv = bus_priv;
|
||||
|
||||
return atomic_read(&pci_priv->drv_connected);
|
||||
}
|
||||
|
||||
void cnss_mhi_controller_set_base(struct cnss_pci_data *pci_priv,
|
||||
phys_addr_t base);
|
||||
int cnss_pci_check_link_status(struct cnss_pci_data *pci_priv);
|
||||
int cnss_suspend_pci_link(struct cnss_pci_data *pci_priv);
|
||||
int cnss_resume_pci_link(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_recover_link_down(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_init(struct cnss_plat_data *plat_priv);
|
||||
void cnss_pci_deinit(struct cnss_plat_data *plat_priv);
|
||||
void cnss_pci_add_fw_prefix_name(struct cnss_pci_data *pci_priv,
|
||||
char *prefix_name, char *name);
|
||||
int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_alloc_qdss_mem(struct cnss_pci_data *pci_priv);
|
||||
void cnss_pci_free_qdss_mem(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_load_tme_patch(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_load_tme_opt_file(struct cnss_pci_data *pci_priv,
|
||||
enum wlfw_tme_lite_file_type_v01 file);
|
||||
int cnss_pci_load_m3(struct cnss_pci_data *pci_priv);
|
||||
void cnss_pci_free_blob_mem(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_load_aux(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_handle_dev_sol_irq(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_start_mhi(struct cnss_pci_data *pci_priv);
|
||||
void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic);
|
||||
#ifdef CONFIG_CNSS2_SSR_DRIVER_DUMP
|
||||
void cnss_pci_collect_host_dump_info(struct cnss_pci_data *pci_priv);
|
||||
#else
|
||||
static inline
|
||||
void cnss_pci_collect_host_dump_info(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
void cnss_pci_device_crashed(struct cnss_pci_data *pci_priv);
|
||||
void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv);
|
||||
u32 cnss_pci_get_wake_msi(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_qmi_send_get(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_qmi_send_put(struct cnss_pci_data *pci_priv);
|
||||
void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_dev_powerup(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_dev_shutdown(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_dev_crash_shutdown(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_dev_ramdump(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_register_driver_hdlr(struct cnss_pci_data *pci_priv, void *data);
|
||||
int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_call_driver_modem_status(struct cnss_pci_data *pci_priv,
|
||||
int modem_current_status);
|
||||
void cnss_pci_pm_runtime_show_usage_count(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_pm_request_resume(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_pm_runtime_resume(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_pm_runtime_get(struct cnss_pci_data *pci_priv,
|
||||
enum cnss_rtpm_id id);
|
||||
int cnss_pci_pm_runtime_get_sync(struct cnss_pci_data *pci_priv,
|
||||
enum cnss_rtpm_id id);
|
||||
void cnss_pci_pm_runtime_get_noresume(struct cnss_pci_data *pci_priv,
|
||||
enum cnss_rtpm_id id);
|
||||
int cnss_pci_pm_runtime_put_autosuspend(struct cnss_pci_data *pci_priv,
|
||||
enum cnss_rtpm_id id);
|
||||
void cnss_pci_pm_runtime_put_noidle(struct cnss_pci_data *pci_priv,
|
||||
enum cnss_rtpm_id id);
|
||||
void cnss_pci_pm_runtime_mark_last_busy(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_update_status(struct cnss_pci_data *pci_priv,
|
||||
enum cnss_driver_status status);
|
||||
int cnss_pci_call_driver_uevent(struct cnss_pci_data *pci_priv,
|
||||
enum cnss_driver_status status, void *data);
|
||||
int cnss_pcie_is_device_down(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_shutdown_cleanup(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_suspend_bus(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_resume_bus(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_debug_reg_read(struct cnss_pci_data *pci_priv, u32 offset,
|
||||
u32 *val, bool raw_access);
|
||||
int cnss_pci_debug_reg_write(struct cnss_pci_data *pci_priv, u32 offset,
|
||||
u32 val, bool raw_access);
|
||||
int cnss_pci_get_iova(struct cnss_pci_data *pci_priv, u64 *addr, u64 *size);
|
||||
int cnss_pci_get_iova_ipa(struct cnss_pci_data *pci_priv, u64 *addr,
|
||||
u64 *size);
|
||||
bool cnss_pci_is_smmu_s1_enabled(struct cnss_pci_data *pci_priv);
|
||||
void cnss_pci_handle_linkdown(struct cnss_pci_data *pci_priv);
|
||||
|
||||
int cnss_pci_update_time_sync_period(struct cnss_pci_data *pci_priv,
|
||||
unsigned int time_sync_period);
|
||||
int cnss_pci_set_therm_cdev_state(struct cnss_pci_data *pci_priv,
|
||||
unsigned long thermal_state,
|
||||
int tcdev_id);
|
||||
int cnss_pci_get_user_msi_assignment(struct cnss_pci_data *pci_priv,
|
||||
char *user_name,
|
||||
int *num_vectors,
|
||||
u32 *user_base_data,
|
||||
u32 *base_vector);
|
||||
void cnss_register_iommu_fault_handler_irq(struct cnss_pci_data *pci_priv);
|
||||
#endif /* _CNSS_PCI_H */
|
@@ -0,0 +1,253 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */
|
||||
|
||||
#ifndef _CNSS_PCI_PLATFORM_H
|
||||
#define _CNSS_PCI_PLATFORM_H
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
#if IS_ENABLED(CONFIG_PCI_MSM)
|
||||
/**
|
||||
* _cnss_pci_enumerate() - Enumerate PCIe endpoints
|
||||
* @plat_priv: driver platform context pointer
|
||||
* @rc_num: root complex index that an endpoint connects to
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to power on root complex and enumerate the endpoint connected to it.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
int _cnss_pci_enumerate(struct cnss_plat_data *plat_priv, u32 rc_num);
|
||||
|
||||
/**
|
||||
* cnss_pci_assert_perst() - Assert PCIe PERST GPIO
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to assert PCIe PERST GPIO.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
int cnss_pci_assert_perst(struct cnss_pci_data *pci_priv);
|
||||
|
||||
/**
|
||||
* cnss_pci_disable_pc() - Disable PCIe link power collapse from RC driver
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
* @vote: value to indicate disable (true) or enable (false)
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to disable PCIe power collapse. The purpose of this API is to avoid
|
||||
* root complex driver still controlling PCIe link from callbacks of
|
||||
* system suspend/resume. Device driver itself should take full control
|
||||
* of the link in such cases.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
int cnss_pci_disable_pc(struct cnss_pci_data *pci_priv, bool vote);
|
||||
|
||||
/**
|
||||
* cnss_pci_set_link_bandwidth() - Update number of lanes and speed of
|
||||
* PCIe link
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
* @link_speed: PCIe link gen speed
|
||||
* @link_width: number of lanes for PCIe link
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to update number of lanes and speed of the link.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
int cnss_pci_set_link_bandwidth(struct cnss_pci_data *pci_priv,
|
||||
u16 link_speed, u16 link_width);
|
||||
|
||||
/**
|
||||
* cnss_pci_set_max_link_speed() - Set the maximum speed PCIe can link up with
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
* @rc_num: root complex index that an endpoint connects to
|
||||
* @link_speed: PCIe link gen speed
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to update the maximum speed that PCIe can link up with.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
int cnss_pci_set_max_link_speed(struct cnss_pci_data *pci_priv,
|
||||
u32 rc_num, u16 link_speed);
|
||||
|
||||
/**
|
||||
* cnss_reg_pci_event() - Register for PCIe events
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to register for PCIe events like link down or WAKE GPIO toggling etc.
|
||||
* The events should be based on PCIe root complex driver's capability.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
int cnss_reg_pci_event(struct cnss_pci_data *pci_priv);
|
||||
void cnss_dereg_pci_event(struct cnss_pci_data *pci_priv);
|
||||
|
||||
/**
|
||||
* cnss_wlan_adsp_pc_enable: Control ADSP power collapse setup
|
||||
* @dev: Platform driver pci private data structure
|
||||
* @control: Power collapse enable / disable
|
||||
*
|
||||
* This function controls ADSP power collapse (PC). It must be called
|
||||
* based on wlan state. ADSP power collapse during wlan RTPM suspend state
|
||||
* results in delay during periodic QMI stats PCI link up/down. This delay
|
||||
* causes additional power consumption.
|
||||
*
|
||||
* Result: 0 Success. negative error codes.
|
||||
*/
|
||||
int cnss_wlan_adsp_pc_enable(struct cnss_pci_data *pci_priv,
|
||||
bool control);
|
||||
int cnss_set_pci_link(struct cnss_pci_data *pci_priv, bool link_up);
|
||||
int cnss_pci_prevent_l1(struct device *dev);
|
||||
void cnss_pci_allow_l1(struct device *dev);
|
||||
int cnss_pci_get_msi_assignment(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_get_one_msi_assignment(struct cnss_pci_data *pci_priv);
|
||||
bool cnss_pci_fallback_one_msi(struct cnss_pci_data *pci_priv,
|
||||
int *num_vectors);
|
||||
bool cnss_pci_is_one_msi(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_get_one_msi_mhi_irq_array_size(struct cnss_pci_data *pci_priv);
|
||||
bool cnss_pci_is_force_one_msi(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv);
|
||||
void cnss_pci_update_drv_supported(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_dsp_link_control(struct cnss_pci_data *pci_priv,
|
||||
bool link_enable);
|
||||
/**
|
||||
* _cnss_pci_get_reg_dump() - Dump PCIe RC registers for debug
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
* @buf: destination buffer pointer
|
||||
* @len: length of the buffer
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver API
|
||||
* to dump PCIe RC registers for debug purpose.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
int _cnss_pci_get_reg_dump(struct cnss_pci_data *pci_priv,
|
||||
u8 *buf, u32 len);
|
||||
int cnss_pci_set_dsp_link_status(struct cnss_pci_data *pci_priv,
|
||||
bool link_enable);
|
||||
int cnss_pci_get_dsp_link_status(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_dsp_link_enable(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_dsp_link_retrain(struct cnss_pci_data *pci_priv,
|
||||
u16 target_link_speed);
|
||||
#else
|
||||
int _cnss_pci_enumerate(struct cnss_plat_data *plat_priv, u32 rc_num)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int cnss_pci_assert_perst(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int cnss_pci_disable_pc(struct cnss_pci_data *pci_priv, bool vote)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_pci_set_link_bandwidth(struct cnss_pci_data *pci_priv,
|
||||
u16 link_speed, u16 link_width)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_pci_set_max_link_speed(struct cnss_pci_data *pci_priv,
|
||||
u32 rc_num, u16 link_speed)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_reg_pci_event(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnss_dereg_pci_event(struct cnss_pci_data *pci_priv) {}
|
||||
|
||||
int cnss_wlan_adsp_pc_enable(struct cnss_pci_data *pci_priv, bool control)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_set_pci_link(struct cnss_pci_data *pci_priv, bool link_up)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_pci_prevent_l1(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_pci_prevent_l1);
|
||||
|
||||
void cnss_pci_allow_l1(struct device *dev)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_pci_allow_l1);
|
||||
|
||||
int cnss_pci_get_msi_assignment(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _cnss_pci_get_reg_dump(struct cnss_pci_data *pci_priv,
|
||||
u8 *buf, u32 len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnss_pci_update_drv_supported(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
pci_priv->drv_supported = false;
|
||||
}
|
||||
|
||||
int cnss_pci_dsp_link_control(struct cnss_pci_data *pci_priv,
|
||||
bool link_enable)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int cnss_pci_set_dsp_link_status(struct cnss_pci_data *pci_priv,
|
||||
bool link_enable)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int cnss_pci_get_dsp_link_status(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int cnss_pci_dsp_link_enable(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int cnss_pci_dsp_link_retrain(struct cnss_pci_data *pci_priv,
|
||||
u16 target_link_speed)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif /* CONFIG_PCI_MSM */
|
||||
|
||||
static inline bool cnss_pci_get_drv_supported(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return pci_priv->drv_supported;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ARCH_QCOM)
|
||||
int cnss_pci_of_reserved_mem_device_init(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_wake_gpio_init(struct cnss_pci_data *pci_priv);
|
||||
void cnss_pci_wake_gpio_deinit(struct cnss_pci_data *pci_priv);
|
||||
#endif /* CONFIG_ARCH_QCOM */
|
||||
#endif /* _CNSS_PCI_PLATFORM_H*/
|
@@ -0,0 +1,829 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */
|
||||
|
||||
#include "pci_platform.h"
|
||||
#include "debug.h"
|
||||
|
||||
static struct cnss_msi_config msi_config = {
|
||||
.total_vectors = 32,
|
||||
.total_users = MSI_USERS,
|
||||
.users = (struct cnss_msi_user[]) {
|
||||
{ .name = "MHI", .num_vectors = 3, .base_vector = 0 },
|
||||
{ .name = "CE", .num_vectors = 10, .base_vector = 3 },
|
||||
{ .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
|
||||
{ .name = "DP", .num_vectors = 18, .base_vector = 14 },
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ONE_MSI_VECTOR
|
||||
/**
|
||||
* All the user share the same vector and msi data
|
||||
* For MHI user, we need pass IRQ array information to MHI component
|
||||
* MHI_IRQ_NUMBER is defined to specify this MHI IRQ array size
|
||||
*/
|
||||
#define MHI_IRQ_NUMBER 3
|
||||
static struct cnss_msi_config msi_config_one_msi = {
|
||||
.total_vectors = 1,
|
||||
.total_users = 4,
|
||||
.users = (struct cnss_msi_user[]) {
|
||||
{ .name = "MHI", .num_vectors = 1, .base_vector = 0 },
|
||||
{ .name = "CE", .num_vectors = 1, .base_vector = 0 },
|
||||
{ .name = "WAKE", .num_vectors = 1, .base_vector = 0 },
|
||||
{ .name = "DP", .num_vectors = 1, .base_vector = 0 },
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
#define ENUM_RETRY_MAX_TIMES 8
|
||||
#define ENUM_RETRY_DELAY_MS 500
|
||||
|
||||
int _cnss_pci_enumerate(struct cnss_plat_data *plat_priv, u32 rc_num)
|
||||
{
|
||||
u32 retry = 0;
|
||||
int ret;
|
||||
|
||||
if (plat_priv->pcie_switch_type == PCIE_SWITCH_NTN3) {
|
||||
while (retry++ < ENUM_RETRY_MAX_TIMES) {
|
||||
ret = msm_pcie_enumerate(rc_num);
|
||||
/* For PCIe switch platform, cnss_probe may called
|
||||
* before PCIe switch hardware ready, wait for
|
||||
* msm_pcie_enumerate complete.
|
||||
*/
|
||||
if (ret == -EPROBE_DEFER) {
|
||||
cnss_pr_dbg("PCIe RC%d not ready, retry:%dth\n",
|
||||
rc_num, retry);
|
||||
msleep(ENUM_RETRY_DELAY_MS);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return msm_pcie_enumerate(rc_num);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cnss_pci_assert_perst(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
struct pci_dev *pci_dev = pci_priv->pci_dev;
|
||||
|
||||
return msm_pcie_pm_control(MSM_PCIE_HANDLE_LINKDOWN,
|
||||
pci_dev->bus->number, pci_dev, NULL,
|
||||
PM_OPTIONS_DEFAULT);
|
||||
}
|
||||
|
||||
int cnss_pci_disable_pc(struct cnss_pci_data *pci_priv, bool vote)
|
||||
{
|
||||
struct pci_dev *pci_dev = pci_priv->pci_dev;
|
||||
|
||||
return msm_pcie_pm_control(vote ? MSM_PCIE_DISABLE_PC :
|
||||
MSM_PCIE_ENABLE_PC,
|
||||
pci_dev->bus->number, pci_dev, NULL,
|
||||
PM_OPTIONS_DEFAULT);
|
||||
}
|
||||
|
||||
int cnss_pci_set_link_bandwidth(struct cnss_pci_data *pci_priv,
|
||||
u16 link_speed, u16 link_width)
|
||||
{
|
||||
return msm_pcie_set_link_bandwidth(pci_priv->pci_dev,
|
||||
link_speed, link_width);
|
||||
}
|
||||
|
||||
int cnss_pci_set_max_link_speed(struct cnss_pci_data *pci_priv,
|
||||
u32 rc_num, u16 link_speed)
|
||||
{
|
||||
return msm_pcie_set_target_link_speed(rc_num, link_speed, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cnss_pci_prevent_l1() - Prevent PCIe L1 and L1 sub-states
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to prevent PCIe link enter L1 and L1 sub-states. The APIs should also
|
||||
* bring link out of L1 or L1 sub-states if any and avoid synchronization
|
||||
* issues if any.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static int _cnss_pci_prevent_l1(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return msm_pcie_prevent_l1(pci_priv->pci_dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cnss_pci_allow_l1() - Allow PCIe L1 and L1 sub-states
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to allow PCIe link enter L1 and L1 sub-states. The APIs should avoid
|
||||
* synchronization issues if any.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static void _cnss_pci_allow_l1(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
msm_pcie_allow_l1(pci_priv->pci_dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_pci_set_link_up() - Power on or resume PCIe link
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to Power on or resume PCIe link.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static int cnss_pci_set_link_up(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
struct pci_dev *pci_dev = pci_priv->pci_dev;
|
||||
enum msm_pcie_pm_opt pm_ops = MSM_PCIE_RESUME;
|
||||
u32 pm_options = PM_OPTIONS_DEFAULT;
|
||||
int ret;
|
||||
|
||||
ret = msm_pcie_pm_control(pm_ops, pci_dev->bus->number, pci_dev,
|
||||
NULL, pm_options);
|
||||
if (ret)
|
||||
cnss_pr_err("Failed to resume PCI link with default option, err = %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_pci_set_link_down() - Power off or suspend PCIe link
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to power off or suspend PCIe link.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static int cnss_pci_set_link_down(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
struct pci_dev *pci_dev = pci_priv->pci_dev;
|
||||
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
|
||||
enum msm_pcie_pm_opt pm_ops;
|
||||
u32 pm_options = PM_OPTIONS_DEFAULT;
|
||||
int ret;
|
||||
|
||||
if (pci_priv->drv_connected_last) {
|
||||
cnss_pr_vdbg("Use PCIe DRV suspend\n");
|
||||
pm_ops = MSM_PCIE_DRV_SUSPEND;
|
||||
} else {
|
||||
if (plat_priv && PCIE_SWITCH_NTN3 == plat_priv->pcie_switch_type) {
|
||||
cnss_pr_dbg("Skip suspend from client side for pcie switch case\n");
|
||||
return 0;
|
||||
}
|
||||
pm_ops = MSM_PCIE_SUSPEND;
|
||||
}
|
||||
|
||||
ret = msm_pcie_pm_control(pm_ops, pci_dev->bus->number, pci_dev,
|
||||
NULL, pm_options);
|
||||
if (ret)
|
||||
cnss_pr_err("Failed to suspend PCI link with default option, err = %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cnss_pci_update_drv_supported(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
struct pci_dev *root_port = pcie_find_root_port(pci_priv->pci_dev);
|
||||
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
|
||||
struct device_node *root_of_node;
|
||||
bool drv_supported = false;
|
||||
|
||||
if (!root_port) {
|
||||
cnss_pr_err("PCIe DRV is not supported as root port is null\n");
|
||||
pci_priv->drv_supported = false;
|
||||
return;
|
||||
}
|
||||
|
||||
root_of_node = root_port->dev.of_node;
|
||||
|
||||
if (root_of_node->parent) {
|
||||
drv_supported = of_property_read_bool(root_of_node->parent,
|
||||
"qcom,drv-supported") ||
|
||||
of_property_read_bool(root_of_node->parent,
|
||||
"qcom,drv-name");
|
||||
}
|
||||
|
||||
cnss_pr_dbg("PCIe DRV is %s\n",
|
||||
drv_supported ? "supported" : "not supported");
|
||||
pci_priv->drv_supported = drv_supported;
|
||||
|
||||
if (drv_supported) {
|
||||
plat_priv->cap.cap_flag |= CNSS_HAS_DRV_SUPPORT;
|
||||
cnss_set_feature_list(plat_priv, CNSS_DRV_SUPPORT_V01);
|
||||
}
|
||||
}
|
||||
|
||||
static void cnss_pci_event_cb(struct msm_pcie_notify *notify)
|
||||
{
|
||||
struct pci_dev *pci_dev;
|
||||
struct cnss_pci_data *pci_priv;
|
||||
struct device *dev;
|
||||
struct cnss_plat_data *plat_priv = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!notify)
|
||||
return;
|
||||
|
||||
pci_dev = notify->user;
|
||||
if (!pci_dev)
|
||||
return;
|
||||
|
||||
pci_priv = cnss_get_pci_priv(pci_dev);
|
||||
if (!pci_priv)
|
||||
return;
|
||||
dev = &pci_priv->pci_dev->dev;
|
||||
|
||||
switch (notify->event) {
|
||||
case MSM_PCIE_EVENT_LINK_RECOVER:
|
||||
cnss_pr_dbg("PCI link recover callback\n");
|
||||
|
||||
plat_priv = pci_priv->plat_priv;
|
||||
if (!plat_priv) {
|
||||
cnss_pr_err("plat_priv is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
plat_priv->ctrl_params.quirks |= BIT(LINK_DOWN_SELF_RECOVERY);
|
||||
|
||||
ret = msm_pcie_pm_control(MSM_PCIE_HANDLE_LINKDOWN,
|
||||
pci_dev->bus->number, pci_dev, NULL,
|
||||
PM_OPTIONS_DEFAULT);
|
||||
if (ret)
|
||||
cnss_pci_handle_linkdown(pci_priv);
|
||||
break;
|
||||
case MSM_PCIE_EVENT_LINKDOWN:
|
||||
cnss_pr_dbg("PCI link down event callback\n");
|
||||
cnss_pci_handle_linkdown(pci_priv);
|
||||
break;
|
||||
case MSM_PCIE_EVENT_WAKEUP:
|
||||
cnss_pr_dbg("PCI Wake up event callback\n");
|
||||
if ((cnss_pci_get_monitor_wake_intr(pci_priv) &&
|
||||
cnss_pci_get_auto_suspended(pci_priv)) ||
|
||||
dev->power.runtime_status == RPM_SUSPENDING) {
|
||||
cnss_pci_set_monitor_wake_intr(pci_priv, false);
|
||||
cnss_pci_pm_request_resume(pci_priv);
|
||||
}
|
||||
complete(&pci_priv->wake_event_complete);
|
||||
break;
|
||||
case MSM_PCIE_EVENT_DRV_CONNECT:
|
||||
cnss_pr_dbg("DRV subsystem is connected\n");
|
||||
cnss_pci_set_drv_connected(pci_priv, 1);
|
||||
break;
|
||||
case MSM_PCIE_EVENT_DRV_DISCONNECT:
|
||||
cnss_pr_dbg("DRV subsystem is disconnected\n");
|
||||
if (cnss_pci_get_auto_suspended(pci_priv))
|
||||
cnss_pci_pm_request_resume(pci_priv);
|
||||
cnss_pci_set_drv_connected(pci_priv, 0);
|
||||
break;
|
||||
default:
|
||||
cnss_pr_err("Received invalid PCI event: %d\n", notify->event);
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_reg_pci_event(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
int ret = 0;
|
||||
struct msm_pcie_register_event *pci_event;
|
||||
|
||||
pci_event = &pci_priv->msm_pci_event;
|
||||
pci_event->events = MSM_PCIE_EVENT_LINK_RECOVER |
|
||||
MSM_PCIE_EVENT_LINKDOWN |
|
||||
MSM_PCIE_EVENT_WAKEUP;
|
||||
|
||||
if (cnss_pci_get_drv_supported(pci_priv))
|
||||
pci_event->events = pci_event->events |
|
||||
MSM_PCIE_EVENT_DRV_CONNECT |
|
||||
MSM_PCIE_EVENT_DRV_DISCONNECT;
|
||||
|
||||
pci_event->user = pci_priv->pci_dev;
|
||||
pci_event->mode = MSM_PCIE_TRIGGER_CALLBACK;
|
||||
pci_event->callback = cnss_pci_event_cb;
|
||||
pci_event->options = MSM_PCIE_CONFIG_NO_RECOVERY;
|
||||
|
||||
ret = msm_pcie_register_event(pci_event);
|
||||
if (ret)
|
||||
cnss_pr_err("Failed to register MSM PCI event, err = %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cnss_dereg_pci_event(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
msm_pcie_deregister_event(&pci_priv->msm_pci_event);
|
||||
}
|
||||
|
||||
int cnss_wlan_adsp_pc_enable(struct cnss_pci_data *pci_priv,
|
||||
bool control)
|
||||
{
|
||||
struct pci_dev *pci_dev = pci_priv->pci_dev;
|
||||
int ret = 0;
|
||||
u32 pm_options = PM_OPTIONS_DEFAULT;
|
||||
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
|
||||
|
||||
if (!cnss_pci_get_drv_supported(pci_priv))
|
||||
return 0;
|
||||
|
||||
if (plat_priv->adsp_pc_enabled == control) {
|
||||
cnss_pr_dbg("ADSP power collapse already %s\n",
|
||||
control ? "Enabled" : "Disabled");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (control)
|
||||
pm_options &= ~MSM_PCIE_CONFIG_NO_DRV_PC;
|
||||
else
|
||||
pm_options |= MSM_PCIE_CONFIG_NO_DRV_PC;
|
||||
|
||||
ret = msm_pcie_pm_control(MSM_PCIE_DRV_PC_CTRL, pci_dev->bus->number,
|
||||
pci_dev, NULL, pm_options);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cnss_pr_dbg("%s ADSP power collapse\n", control ? "Enable" : "Disable");
|
||||
plat_priv->adsp_pc_enabled = control;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_set_pci_link_status(struct cnss_pci_data *pci_priv,
|
||||
enum pci_link_status status)
|
||||
{
|
||||
u16 link_speed, link_width = pci_priv->def_link_width;
|
||||
u16 one_lane = PCI_EXP_LNKSTA_NLW_X1 >> PCI_EXP_LNKSTA_NLW_SHIFT;
|
||||
int ret;
|
||||
|
||||
cnss_pr_vdbg("Set PCI link status to: %u\n", status);
|
||||
|
||||
switch (status) {
|
||||
case PCI_GEN1:
|
||||
link_speed = PCI_EXP_LNKSTA_CLS_2_5GB;
|
||||
if (!link_width)
|
||||
link_width = one_lane;
|
||||
break;
|
||||
case PCI_GEN2:
|
||||
link_speed = PCI_EXP_LNKSTA_CLS_5_0GB;
|
||||
if (!link_width)
|
||||
link_width = one_lane;
|
||||
break;
|
||||
case PCI_DEF:
|
||||
link_speed = pci_priv->def_link_speed;
|
||||
if (!link_speed || !link_width) {
|
||||
cnss_pr_err("PCI link speed or width is not valid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cnss_pr_err("Unknown PCI link status config: %u\n", status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = cnss_pci_set_link_bandwidth(pci_priv, link_speed, link_width);
|
||||
if (!ret)
|
||||
pci_priv->cur_link_speed = link_speed;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cnss_set_pci_link(struct cnss_pci_data *pci_priv, bool link_up)
|
||||
{
|
||||
int ret = 0, retry = 0;
|
||||
struct cnss_plat_data *plat_priv;
|
||||
int sw_ctrl_gpio;
|
||||
|
||||
plat_priv = pci_priv->plat_priv;
|
||||
sw_ctrl_gpio = plat_priv->pinctrl_info.sw_ctrl_gpio;
|
||||
|
||||
cnss_pr_vdbg("%s PCI link\n", link_up ? "Resuming" : "Suspending");
|
||||
|
||||
if (link_up) {
|
||||
retry:
|
||||
ret = cnss_pci_set_link_up(pci_priv);
|
||||
if (ret && retry++ < LINK_TRAINING_RETRY_MAX_TIMES) {
|
||||
cnss_pr_dbg("Retry PCI link training #%d\n", retry);
|
||||
cnss_pr_dbg("Value of SW_CTRL GPIO: %d\n",
|
||||
cnss_get_input_gpio_value(plat_priv, sw_ctrl_gpio));
|
||||
if (pci_priv->pci_link_down_ind)
|
||||
msleep(LINK_TRAINING_RETRY_DELAY_MS * retry);
|
||||
goto retry;
|
||||
}
|
||||
} else {
|
||||
/* Since DRV suspend cannot be done in Gen 3, set it to
|
||||
* Gen 2 if current link speed is larger than Gen 2.
|
||||
*/
|
||||
if (pci_priv->drv_connected_last &&
|
||||
pci_priv->cur_link_speed > PCI_EXP_LNKSTA_CLS_5_0GB)
|
||||
cnss_set_pci_link_status(pci_priv, PCI_GEN2);
|
||||
|
||||
ret = cnss_pci_set_link_down(pci_priv);
|
||||
}
|
||||
|
||||
if (pci_priv->drv_connected_last) {
|
||||
if ((link_up && !ret) || (!link_up && ret))
|
||||
cnss_set_pci_link_status(pci_priv, PCI_DEF);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCIE_SWITCH_SUPPORT
|
||||
int cnss_pci_dsp_link_control(struct cnss_pci_data *pci_priv,
|
||||
bool link_enable)
|
||||
{
|
||||
if (!pci_priv)
|
||||
return -ENODEV;
|
||||
|
||||
pci_priv->pci_dsp_link_status = link_enable;
|
||||
return msm_pcie_dsp_link_control(pci_priv->pci_dev, link_enable);
|
||||
}
|
||||
|
||||
int cnss_pci_set_dsp_link_status(struct cnss_pci_data *pci_priv,
|
||||
bool link_enable)
|
||||
{
|
||||
if (!pci_priv)
|
||||
return -ENODEV;
|
||||
|
||||
pci_priv->pci_dsp_link_status = link_enable;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_pci_get_dsp_link_status(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
if (!pci_priv)
|
||||
return -ENODEV;
|
||||
|
||||
return pci_priv->pci_dsp_link_status;
|
||||
}
|
||||
|
||||
int cnss_pci_dsp_link_enable(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
int ret = 0;
|
||||
int retry_count = 0;
|
||||
struct cnss_plat_data *plat_priv;
|
||||
|
||||
if (!pci_priv)
|
||||
return -ENODEV;
|
||||
|
||||
plat_priv = pci_priv->plat_priv;
|
||||
/* For PCIe switch platform, wait for link train of DSP<->WLAN complete
|
||||
*/
|
||||
while (retry_count++ < DSP_LINK_ENABLE_RETRY_COUNT_MAX) {
|
||||
ret = cnss_pci_dsp_link_control(pci_priv, true);
|
||||
if (!ret)
|
||||
break;
|
||||
|
||||
cnss_pci_dsp_link_control(pci_priv, false);
|
||||
cnss_pr_err("DSP<->WLAN link train failed, retry...\n");
|
||||
cnss_select_pinctrl_state(plat_priv, false);
|
||||
usleep_range(DSP_LINK_ENABLE_DELAY_TIME_US_MIN,
|
||||
DSP_LINK_ENABLE_DELAY_TIME_US_MAX);
|
||||
ret = cnss_select_pinctrl_enable(plat_priv);
|
||||
if (ret) {
|
||||
cnss_pr_err("Failed to select pinctrl state, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
usleep_range(DSP_LINK_ENABLE_DELAY_TIME_US_MIN,
|
||||
DSP_LINK_ENABLE_DELAY_TIME_US_MAX);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCIE_SWITCH_RETRAIN_LINK_SUPPORT
|
||||
int cnss_pci_dsp_link_retrain(struct cnss_pci_data *pci_priv,
|
||||
u16 target_link_speed)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!pci_priv)
|
||||
return -ENODEV;
|
||||
|
||||
cnss_pr_dbg("Setting DSP <-> EP link speed:0x%x\n", target_link_speed);
|
||||
|
||||
ret = msm_pcie_retrain_port_link(pci_priv->pci_dev, target_link_speed);
|
||||
if (ret) {
|
||||
cnss_pr_err("Failed to retrain link, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pci_priv->def_link_speed = target_link_speed;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
int cnss_pci_dsp_link_retrain(struct cnss_pci_data *pci_priv,
|
||||
u16 target_link_speed)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
int cnss_pci_dsp_link_control(struct cnss_pci_data *pci_priv,
|
||||
bool link_enable)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int cnss_pci_set_dsp_link_status(struct cnss_pci_data *pci_priv,
|
||||
bool link_enable)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int cnss_pci_get_dsp_link_status(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int cnss_pci_dsp_link_enable(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int cnss_pci_dsp_link_retrain(struct cnss_pci_data *pci_priv,
|
||||
u16 target_link_speed)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
|
||||
int cnss_pci_prevent_l1(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||
struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
|
||||
int ret;
|
||||
|
||||
if (!pci_priv) {
|
||||
cnss_pr_err("pci_priv is NULL\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (pci_priv->pci_link_state == PCI_LINK_DOWN) {
|
||||
cnss_pr_dbg("PCIe link is in suspend state\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (pci_priv->pci_link_down_ind) {
|
||||
cnss_pr_err("PCIe link is down\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = _cnss_pci_prevent_l1(pci_priv);
|
||||
if (ret == -EIO) {
|
||||
cnss_pr_err("Failed to prevent PCIe L1, considered as link down\n");
|
||||
cnss_pci_link_down(dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_pci_prevent_l1);
|
||||
|
||||
void cnss_pci_allow_l1(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||
struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
|
||||
|
||||
if (!pci_priv) {
|
||||
cnss_pr_err("pci_priv is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pci_priv->pci_link_state == PCI_LINK_DOWN) {
|
||||
cnss_pr_dbg("PCIe link is in suspend state\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pci_priv->pci_link_down_ind) {
|
||||
cnss_pr_err("PCIe link is down\n");
|
||||
return;
|
||||
}
|
||||
|
||||
_cnss_pci_allow_l1(pci_priv);
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_pci_allow_l1);
|
||||
|
||||
int cnss_pci_get_msi_assignment(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
pci_priv->msi_config = &msi_config;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ONE_MSI_VECTOR
|
||||
int cnss_pci_get_one_msi_assignment(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
pci_priv->msi_config = &msi_config_one_msi;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool cnss_pci_fallback_one_msi(struct cnss_pci_data *pci_priv,
|
||||
int *num_vectors)
|
||||
{
|
||||
struct pci_dev *pci_dev = pci_priv->pci_dev;
|
||||
struct cnss_msi_config *msi_config;
|
||||
|
||||
cnss_pci_get_one_msi_assignment(pci_priv);
|
||||
msi_config = pci_priv->msi_config;
|
||||
if (!msi_config) {
|
||||
cnss_pr_err("one msi_config is NULL!\n");
|
||||
return false;
|
||||
}
|
||||
*num_vectors = pci_alloc_irq_vectors(pci_dev,
|
||||
msi_config->total_vectors,
|
||||
msi_config->total_vectors,
|
||||
PCI_IRQ_MSI);
|
||||
if (*num_vectors < 0) {
|
||||
cnss_pr_err("Failed to get one MSI vector!\n");
|
||||
return false;
|
||||
}
|
||||
cnss_pr_dbg("request MSI one vector\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cnss_pci_is_one_msi(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return pci_priv && pci_priv->msi_config &&
|
||||
(pci_priv->msi_config->total_vectors == 1);
|
||||
}
|
||||
|
||||
int cnss_pci_get_one_msi_mhi_irq_array_size(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return MHI_IRQ_NUMBER;
|
||||
}
|
||||
|
||||
bool cnss_pci_is_force_one_msi(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
|
||||
|
||||
return test_bit(FORCE_ONE_MSI, &plat_priv->ctrl_params.quirks);
|
||||
}
|
||||
#else
|
||||
int cnss_pci_get_one_msi_assignment(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool cnss_pci_fallback_one_msi(struct cnss_pci_data *pci_priv,
|
||||
int *num_vectors)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cnss_pci_is_one_msi(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int cnss_pci_get_one_msi_mhi_irq_array_size(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool cnss_pci_is_force_one_msi(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int cnss_pci_smmu_fault_handler(struct iommu_domain *domain,
|
||||
struct device *dev, unsigned long iova,
|
||||
int flags, void *handler_token)
|
||||
{
|
||||
struct cnss_pci_data *pci_priv = handler_token;
|
||||
|
||||
cnss_fatal_err("SMMU fault happened with IOVA 0x%lx\n", iova);
|
||||
|
||||
if (!pci_priv) {
|
||||
cnss_pr_err("pci_priv is NULL\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pci_priv->is_smmu_fault = true;
|
||||
cnss_pci_update_status(pci_priv, CNSS_FW_DOWN);
|
||||
cnss_force_fw_assert(&pci_priv->pci_dev->dev);
|
||||
|
||||
/* IOMMU driver requires -ENOSYS to print debug info. */
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
struct pci_dev *pci_dev = pci_priv->pci_dev;
|
||||
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
|
||||
struct device_node *of_node;
|
||||
struct resource *res;
|
||||
const char *iommu_dma_type;
|
||||
u32 addr_win[2];
|
||||
int ret = 0;
|
||||
|
||||
of_node = of_parse_phandle(pci_dev->dev.of_node, "qcom,iommu-group", 0);
|
||||
if (!of_node)
|
||||
return ret;
|
||||
|
||||
cnss_pr_dbg("Initializing SMMU\n");
|
||||
|
||||
pci_priv->iommu_domain = iommu_get_domain_for_dev(&pci_dev->dev);
|
||||
ret = of_property_read_string(of_node, "qcom,iommu-dma",
|
||||
&iommu_dma_type);
|
||||
if (!ret && !strcmp("fastmap", iommu_dma_type)) {
|
||||
cnss_pr_dbg("Enabling SMMU S1 stage\n");
|
||||
pci_priv->smmu_s1_enable = true;
|
||||
iommu_set_fault_handler(pci_priv->iommu_domain,
|
||||
cnss_pci_smmu_fault_handler, pci_priv);
|
||||
cnss_register_iommu_fault_handler_irq(pci_priv);
|
||||
}
|
||||
|
||||
ret = of_property_read_u32_array(of_node, "qcom,iommu-dma-addr-pool",
|
||||
addr_win, ARRAY_SIZE(addr_win));
|
||||
if (ret) {
|
||||
cnss_pr_err("Invalid SMMU size window, err = %d\n", ret);
|
||||
of_node_put(of_node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pci_priv->smmu_iova_start = addr_win[0];
|
||||
pci_priv->smmu_iova_len = addr_win[1];
|
||||
cnss_pr_dbg("smmu_iova_start: %pa, smmu_iova_len: 0x%zx\n",
|
||||
&pci_priv->smmu_iova_start,
|
||||
pci_priv->smmu_iova_len);
|
||||
|
||||
res = platform_get_resource_byname(plat_priv->plat_dev, IORESOURCE_MEM,
|
||||
"smmu_iova_ipa");
|
||||
if (res) {
|
||||
pci_priv->smmu_iova_ipa_start = res->start;
|
||||
pci_priv->smmu_iova_ipa_current = res->start;
|
||||
pci_priv->smmu_iova_ipa_len = resource_size(res);
|
||||
cnss_pr_dbg("smmu_iova_ipa_start: %pa, smmu_iova_ipa_len: 0x%zx\n",
|
||||
&pci_priv->smmu_iova_ipa_start,
|
||||
pci_priv->smmu_iova_ipa_len);
|
||||
}
|
||||
|
||||
pci_priv->iommu_geometry = of_property_read_bool(of_node,
|
||||
"qcom,iommu-geometry");
|
||||
cnss_pr_dbg("iommu_geometry: %d\n", pci_priv->iommu_geometry);
|
||||
|
||||
of_node_put(of_node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _cnss_pci_get_reg_dump(struct cnss_pci_data *pci_priv,
|
||||
u8 *buf, u32 len)
|
||||
{
|
||||
return msm_pcie_reg_dump(pci_priv->pci_dev, buf, len);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ARCH_QCOM)
|
||||
/**
|
||||
* cnss_pci_of_reserved_mem_device_init() - Assign reserved memory region
|
||||
* to given PCI device
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
*
|
||||
* This function shall call corresponding of_reserved_mem_device* API to
|
||||
* assign reserved memory region to PCI device based on where the memory is
|
||||
* defined and attached to (platform device of_node or PCI device of_node)
|
||||
* in device tree.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
int cnss_pci_of_reserved_mem_device_init(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
struct device *dev_pci = &pci_priv->pci_dev->dev;
|
||||
int ret;
|
||||
|
||||
/* Use of_reserved_mem_device_init_by_idx() if reserved memory is
|
||||
* attached to platform device of_node.
|
||||
*/
|
||||
ret = of_reserved_mem_device_init(dev_pci);
|
||||
if (ret) {
|
||||
if (ret == -EINVAL)
|
||||
cnss_pr_vdbg("Ignore, no specific reserved-memory assigned\n");
|
||||
else
|
||||
cnss_pr_err("Failed to init reserved mem device, err = %d\n",
|
||||
ret);
|
||||
}
|
||||
if (dev_pci->cma_area)
|
||||
cnss_pr_dbg("CMA area is %s\n",
|
||||
cma_get_name(dev_pci->cma_area));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cnss_pci_wake_gpio_init(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnss_pci_wake_gpio_deinit(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
@@ -0,0 +1,12 @@
|
||||
CONFIG_CNSS2=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
||||
CONFIG_CNSS2_QMI=y
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_BUS_AUTO_SUSPEND=y
|
||||
CONFIG_CNSS2_SSR_DRIVER_DUMP=y
|
||||
CONFIG_CNSS_HW_SECURE_DISABLE=y
|
||||
CONFIG_CNSS_HW_SECURE_SMEM=y
|
||||
CONFIG_CNSS2_SMMU_DB_SUPPORT=y
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS2_DEBUG=y
|
@@ -0,0 +1,11 @@
|
||||
CONFIG_CNSS2=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
||||
CONFIG_CNSS2_QMI=y
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_BUS_AUTO_SUSPEND=y
|
||||
CONFIG_CNSS2_SSR_DRIVER_DUMP=y
|
||||
CONFIG_CNSS_HW_SECURE_DISABLE=y
|
||||
CONFIG_CNSS_HW_SECURE_SMEM=y
|
||||
CONFIG_CNSS2_SMMU_DB_SUPPORT=y
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
文件差异内容过多而无法显示
加载差异
文件差异内容过多而无法显示
加载差异
@@ -0,0 +1,356 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _CNSS_QMI_H
|
||||
#define _CNSS_QMI_H
|
||||
|
||||
#include "wlan_firmware_service_v01.h"
|
||||
|
||||
struct cnss_plat_data;
|
||||
|
||||
struct cnss_qmi_event_server_arrive_data {
|
||||
unsigned int node;
|
||||
unsigned int port;
|
||||
};
|
||||
|
||||
struct cnss_mem_seg {
|
||||
u64 addr;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct cnss_qmi_event_fw_mem_file_save_data {
|
||||
u32 total_size;
|
||||
u32 mem_seg_len;
|
||||
enum wlfw_mem_type_enum_v01 mem_type;
|
||||
struct cnss_mem_seg mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
|
||||
char file_name[QMI_WLFW_MAX_STR_LEN_V01 + 1];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CNSS2_QMI
|
||||
#include "coexistence_service_v01.h"
|
||||
#include "ip_multimedia_subsystem_private_service_v01.h"
|
||||
#include "device_management_service_v01.h"
|
||||
|
||||
int cnss_qmi_init(struct cnss_plat_data *plat_priv);
|
||||
void cnss_qmi_deinit(struct cnss_plat_data *plat_priv);
|
||||
unsigned int cnss_get_qmi_timeout(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv, void *data);
|
||||
int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u32 bdf_type);
|
||||
int cnss_wlfw_tme_patch_dnld_send_sync(struct cnss_plat_data *plat_priv,
|
||||
enum wlfw_tme_lite_file_type_v01 file);
|
||||
int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_aux_dnld_send_sync(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_driver_mode mode);
|
||||
int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
|
||||
struct cnss_wlan_enable_cfg *config,
|
||||
const char *host_version);
|
||||
int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u32 offset, u32 mem_type,
|
||||
u32 data_len, u8 *data);
|
||||
int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u32 offset, u32 mem_type,
|
||||
u32 data_len, u8 *data);
|
||||
int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u8 fw_log_mode);
|
||||
int cnss_wlfw_antenna_switch_send_sync(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_antenna_grant_send_sync(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_dynamic_feature_mask_send_sync(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_get_info_send_sync(struct cnss_plat_data *plat_priv, int type,
|
||||
void *cmd, int cmd_len);
|
||||
int cnss_process_wfc_call_ind_event(struct cnss_plat_data *plat_priv,
|
||||
void *data);
|
||||
int cnss_process_twt_cfg_ind_event(struct cnss_plat_data *plat_priv,
|
||||
void *data);
|
||||
int cnss_register_coex_service(struct cnss_plat_data *plat_priv);
|
||||
void cnss_unregister_coex_service(struct cnss_plat_data *plat_priv);
|
||||
int coex_antenna_switch_to_wlan_send_sync_msg(struct cnss_plat_data *plat_priv);
|
||||
int coex_antenna_switch_to_mdm_send_sync_msg(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_qdss_trace_mem_info_send_sync(struct cnss_plat_data *plat_priv);
|
||||
int cnss_register_ims_service(struct cnss_plat_data *plat_priv);
|
||||
void cnss_unregister_ims_service(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_send_pcie_gen_speed_sync(struct cnss_plat_data *plat_priv);
|
||||
void cnss_ignore_qmi_failure(bool ignore);
|
||||
int cnss_qmi_get_dms_mac(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_wlan_mac_req_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u8 *mac, u32 mac_len);
|
||||
int cnss_dms_init(struct cnss_plat_data *plat_priv);
|
||||
void cnss_dms_deinit(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_qdss_data_send_sync(struct cnss_plat_data *plat_priv, char *file_name,
|
||||
u32 total_size);
|
||||
int cnss_wlfw_tme_opt_file_dnld_send_sync(struct cnss_plat_data *plat_priv,
|
||||
enum wlfw_tme_lite_file_type_v01 file);
|
||||
int wlfw_qdss_trace_start(struct cnss_plat_data *plat_priv);
|
||||
int wlfw_qdss_trace_stop(struct cnss_plat_data *plat_priv, unsigned long long option);
|
||||
int cnss_wlfw_cal_report_req_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u32 cal_file_download_size);
|
||||
int cnss_send_subsys_restart_level_msg(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_send_host_wfc_call_status(struct cnss_plat_data *plat_priv,
|
||||
struct cnss_wfc_cfg cfg);
|
||||
void cnss_cancel_dms_work(void);
|
||||
#else
|
||||
#define QMI_WLFW_TIMEOUT_MS 10000
|
||||
|
||||
static inline int cnss_qmi_init(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void cnss_qmi_deinit(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned int cnss_get_qmi_timeout(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return QMI_WLFW_TIMEOUT_MS;
|
||||
}
|
||||
|
||||
static inline int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv,
|
||||
void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u32 bdf_type)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int cnss_wlfw_aux_dnld_send_sync(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_driver_mode mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
|
||||
struct cnss_wlan_enable_cfg *config,
|
||||
const char *host_version)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u32 offset, u32 mem_type,
|
||||
u32 data_len, u8 *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u32 offset, u32 mem_type,
|
||||
u32 data_len, u8 *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u8 fw_log_mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_antenna_switch_send_sync(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_antenna_grant_send_sync(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_dynamic_feature_mask_send_sync(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_get_info_send_sync(struct cnss_plat_data *plat_priv, int type,
|
||||
void *cmd, int cmd_len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_process_wfc_call_ind_event(struct cnss_plat_data *plat_priv,
|
||||
void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_process_twt_cfg_ind_event(struct cnss_plat_data *plat_priv,
|
||||
void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_register_coex_service(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
void cnss_unregister_coex_service(struct cnss_plat_data *plat_priv) {}
|
||||
|
||||
static inline
|
||||
int coex_antenna_switch_to_wlan_send_sync_msg(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int coex_antenna_switch_to_mdm_send_sync_msg(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_qdss_trace_mem_info_send_sync(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_register_ims_service(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
void cnss_unregister_ims_service(struct cnss_plat_data *plat_priv) {}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_send_pcie_gen_speed_sync(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void cnss_ignore_qmi_failure(bool ignore) {};
|
||||
static inline int cnss_qmi_get_dms_mac(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_wlfw_wlan_mac_req_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u8 *mac, u32 mac_len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int cnss_dms_init(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_wlfw_qdss_data_send_sync(struct cnss_plat_data *plat_priv, char *file_name,
|
||||
u32 total_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_wlfw_tme_opt_file_dnld_send_sync(struct cnss_plat_data *plat_priv,
|
||||
enum wlfw_tme_lite_file_type_v01 file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void cnss_dms_deinit(struct cnss_plat_data *plat_priv) {}
|
||||
|
||||
int wlfw_qdss_trace_start(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wlfw_qdss_trace_stop(struct cnss_plat_data *plat_priv, unsigned long long option)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_cal_report_req_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u32 cal_file_download_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_send_subsys_restart_level_msg(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cnss_cancel_dms_work(void)
|
||||
{
|
||||
}
|
||||
|
||||
int cnss_wlfw_send_host_wfc_call_status(struct cnss_plat_data *plat_priv,
|
||||
struct cnss_wfc_cfg cfg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_CNSS2_QMI */
|
||||
|
||||
#ifdef CONFIG_CNSS2_DEBUG
|
||||
static inline u32 cnss_get_host_build_type(void)
|
||||
{
|
||||
return QMI_HOST_BUILD_TYPE_PRIMARY_V01;
|
||||
}
|
||||
#else
|
||||
static inline u32 cnss_get_host_build_type(void)
|
||||
{
|
||||
return QMI_HOST_BUILD_TYPE_SECONDARY_V01;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _CNSS_QMI_H */
|
@@ -0,0 +1,380 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CNSS_REG_H
|
||||
#define _CNSS_REG_H
|
||||
|
||||
#define QCA6390_PCIE_REMAP_BAR_CTRL_OFFSET 0x310C
|
||||
#define PEACH_PCIE_REMAP_BAR_CTRL_OFFSET 0x3278
|
||||
|
||||
#define QCA6390_CE_SRC_RING_REG_BASE 0xA00000
|
||||
#define QCA6390_CE_DST_RING_REG_BASE 0xA01000
|
||||
#define QCA6390_CE_COMMON_REG_BASE 0xA18000
|
||||
|
||||
#define QCA6490_CE_SRC_RING_REG_BASE 0x1B80000
|
||||
#define QCA6490_CE_DST_RING_REG_BASE 0x1B81000
|
||||
#define QCA6490_CE_COMMON_REG_BASE 0x1B98000
|
||||
|
||||
#define CE_SRC_RING_BASE_LSB_OFFSET 0x0
|
||||
#define CE_SRC_RING_BASE_MSB_OFFSET 0x4
|
||||
#define CE_SRC_RING_ID_OFFSET 0x8
|
||||
#define CE_SRC_RING_MISC_OFFSET 0x10
|
||||
#define CE_SRC_CTRL_OFFSET 0x58
|
||||
#define CE_SRC_R0_CE_CH_SRC_IS_OFFSET 0x5C
|
||||
#define CE_SRC_RING_HP_OFFSET 0x400
|
||||
#define CE_SRC_RING_TP_OFFSET 0x404
|
||||
|
||||
#define CE_DEST_RING_BASE_LSB_OFFSET 0x0
|
||||
#define CE_DEST_RING_BASE_MSB_OFFSET 0x4
|
||||
#define CE_DEST_RING_ID_OFFSET 0x8
|
||||
#define CE_DEST_RING_MISC_OFFSET 0x10
|
||||
#define CE_DEST_CTRL_OFFSET 0xB0
|
||||
#define CE_CH_DST_IS_OFFSET 0xB4
|
||||
#define CE_CH_DEST_CTRL2_OFFSET 0xB8
|
||||
#define CE_DEST_RING_HP_OFFSET 0x400
|
||||
#define CE_DEST_RING_TP_OFFSET 0x404
|
||||
|
||||
#define CE_STATUS_RING_BASE_LSB_OFFSET 0x58
|
||||
#define CE_STATUS_RING_BASE_MSB_OFFSET 0x5C
|
||||
#define CE_STATUS_RING_ID_OFFSET 0x60
|
||||
#define CE_STATUS_RING_MISC_OFFSET 0x68
|
||||
#define CE_STATUS_RING_HP_OFFSET 0x408
|
||||
#define CE_STATUS_RING_TP_OFFSET 0x40C
|
||||
|
||||
#define CE_COMMON_GXI_ERR_INTS 0x14
|
||||
#define CE_COMMON_GXI_ERR_STATS 0x18
|
||||
#define CE_COMMON_GXI_WDOG_STATUS 0x2C
|
||||
#define CE_COMMON_TARGET_IE_0 0x48
|
||||
#define CE_COMMON_TARGET_IE_1 0x4C
|
||||
|
||||
#define CE_REG_INTERVAL 0x2000
|
||||
|
||||
#define SHADOW_REG_COUNT 36
|
||||
#define SHADOW_REG_LEN_BYTES 4
|
||||
#define PCIE_SHADOW_REG_VALUE_0 0x8FC
|
||||
#define PCIE_SHADOW_REG_VALUE_1 0x900
|
||||
#define PCIE_SHADOW_REG_VALUE_34 0x984
|
||||
#define PCIE_SHADOW_REG_VALUE_35 0x988
|
||||
|
||||
#define SHADOW_REG_INTER_COUNT 43
|
||||
#define PCIE_SHADOW_REG_INTER_0 0x1E05000
|
||||
|
||||
#define PCIE_MHI_TIME_LOW 0xA28
|
||||
#define PCIE_MHI_TIME_HIGH 0xA2C
|
||||
|
||||
#define QDSS_APB_DEC_CSR_BASE 0x1C01000
|
||||
|
||||
#define QDSS_APB_DEC_CSR_ETRIRQCTRL_OFFSET 0x6C
|
||||
#define QDSS_APB_DEC_CSR_PRESERVEETF_OFFSET 0x70
|
||||
#define QDSS_APB_DEC_CSR_PRESERVEETR0_OFFSET 0x74
|
||||
#define QDSS_APB_DEC_CSR_PRESERVEETR1_OFFSET 0x78
|
||||
|
||||
#define MAX_UNWINDOWED_ADDRESS 0x80000
|
||||
#define WINDOW_ENABLE_BIT 0x40000000
|
||||
#define WINDOW_SHIFT 19
|
||||
#define WINDOW_VALUE_MASK 0x3F
|
||||
#define WINDOW_START MAX_UNWINDOWED_ADDRESS
|
||||
#define WINDOW_RANGE_MASK 0x7FFFF
|
||||
|
||||
#define TIME_SYNC_ENABLE 0x80000000
|
||||
#define TIME_SYNC_CLEAR 0x0
|
||||
|
||||
#define QCA6390_DEBUG_PBL_LOG_SRAM_START 0x01403D58
|
||||
#define QCA6390_DEBUG_PBL_LOG_SRAM_MAX_SIZE 80
|
||||
#define QCA6390_DEBUG_SBL_LOG_SRAM_MAX_SIZE 44
|
||||
|
||||
#define QCA6490_DEBUG_PBL_LOG_SRAM_START 0x01403DA0
|
||||
#define QCA6490_DEBUG_PBL_LOG_SRAM_MAX_SIZE 40
|
||||
#define QCA6490_DEBUG_SBL_LOG_SRAM_MAX_SIZE 48
|
||||
|
||||
#define KIWI_DEBUG_PBL_LOG_SRAM_START 0x01403D98
|
||||
#define KIWI_DEBUG_PBL_LOG_SRAM_MAX_SIZE 40
|
||||
#define KIWI_DEBUG_SBL_LOG_SRAM_MAX_SIZE 48
|
||||
#define KIWI_PBL_BOOTSTRAP_STATUS 0x01A10008
|
||||
|
||||
#define MANGO_DEBUG_PBL_LOG_SRAM_START 0x01403D98
|
||||
#define MANGO_DEBUG_PBL_LOG_SRAM_MAX_SIZE 40
|
||||
#define MANGO_DEBUG_SBL_LOG_SRAM_MAX_SIZE 48
|
||||
#define MANGO_PBL_BOOTSTRAP_STATUS 0x01A10008
|
||||
|
||||
#define PEACH_DEBUG_PBL_LOG_SRAM_START 0x01403640
|
||||
#define PEACH_DEBUG_PBL_LOG_SRAM_MAX_SIZE 40
|
||||
#define PEACH_DEBUG_SBL_LOG_SRAM_MAX_SIZE 48
|
||||
#define PEACH_PBL_BOOTSTRAP_STATUS 0x01A10008
|
||||
|
||||
#define TCSR_PBL_LOGGING_REG 0x01B000F8
|
||||
#define PCIE_BHI_ERRDBG2_REG 0x01E0E238
|
||||
#define PCIE_BHI_ERRDBG3_REG 0x01E0E23C
|
||||
#define PBL_WLAN_BOOT_CFG 0x01E22B34
|
||||
#define PBL_BOOTSTRAP_STATUS 0x01910008
|
||||
#define SRAM_START 0x01400000
|
||||
#define SRAM_END 0x01800000
|
||||
#define SRAM_DUMP_SIZE 0x400000
|
||||
|
||||
#define QCA6390_PCIE_SOC_WDOG_DISC_BAD_DATA_LOW_CFG_SOC_PCIE_REG 0x01E04234
|
||||
#define QCA6390_PCIE_SOC_WDOG_DISC_BAD_DATA_LOW_CFG_SOC_PCIE_REG_VAL 0xDEAD1234
|
||||
#define PEACH_PCIE_SOC_WDOG_DISC_BAD_DATA_LOW_CFG_SOC_PCIE_REG 0x01E04334
|
||||
#define PEACH_PCIE_SOC_WDOG_DISC_BAD_DATA_LOW_CFG_SOC_PCIE_REG_VAL 0xDEAD1334
|
||||
#define QCA6390_PCIE_PCIE_WCSS_STATUS_FOR_DEBUG_LOW_PCIE_LOCAL_REG 0x01E03140
|
||||
#define PEACH_PCIE_PCIE_WCSS_STATUS_FOR_DEBUG_LOW_PCIE_LOCAL_REG 0x01E03284
|
||||
#define QCA6390_PCIE_SOC_PCIE_WRAP_INTR_MASK_SOC_PCIE_REG 0x1E04054
|
||||
#define QCA6390_PCIE_SOC_PCIE_WRAP_INTR_STATUS_SOC_PCIE_REG 0x1E04058
|
||||
#define QCA6390_PCIE_SOC_COMMIT_REPLAY_SOC_PCIE_REG 0x01E05090
|
||||
#define PEACH_PCIE_SOC_COMMIT_REPLAY_SOC_PCIE_REG 0x01E01100
|
||||
#define QCA6390_PCIE_SOC_PCIE_REG_PCIE_SCRATCH_2_SOC_PCIE_REG 0x01E0405C
|
||||
#define QCA6390_PCIE_PCIE_PARF_LTSSM 0x01E081B0
|
||||
#define QCA6390_PCIE_PCIE_PARF_PM_STTS 0x01E08024
|
||||
#define QCA6390_PCIE_PCIE_PARF_PM_STTS_1 0x01E08028
|
||||
#define QCA6390_PCIE_PCIE_PARF_INT_STATUS 0x01E08220
|
||||
#define QCA6390_PCIE_PCIE_INT_ALL_STATUS 0x01E08224
|
||||
#define QCA6390_PCIE_PCIE_INT_ALL_MASK 0x01E0822C
|
||||
#define QCA6390_PCIE_PCIE_PARF_BDF_TO_SID_CFG 0x01E0AC00
|
||||
#define QCA6390_PCIE_PCIE_PARF_L1SS_SLEEP_NO_MHI_ACCESS_HANDLER_RD_4 0x01E08530
|
||||
#define QCA6390_PCIE_PCIE_PARF_L1SS_SLEEP_NO_MHI_ACCESS_HANDLER_RD_3 0x01E0852c
|
||||
#define QCA6390_PCIE_PCIE_PARF_MHI_CLOCK_RESET_CTRL 0x01E08174
|
||||
#define QCA6390_PCIE_PCIE_PARF_MHI_BASE_ADDR_LOWER 0x01E08178
|
||||
#define QCA6390_PCIE_PCIE_PARF_L1SS_SLEEP_MODE_HANDLER_STATUS 0x01E084D0
|
||||
#define QCA6390_PCIE_PCIE_PARF_L1SS_SLEEP_MODE_HANDLER_CFG 0x01E084d4
|
||||
#define QCA6390_PCIE_PCIE_PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L2 0x01E0ec88
|
||||
#define QCA6390_PCIE_PCIE_PARF_DEBUG_CNT_PM_LINKST_IN_L1SUB 0x01E0ec08
|
||||
#define QCA6390_PCIE_PCIE_CORE_CONFIG 0x01E08640
|
||||
#define QCA6390_PCIE_PCIE_PARF_DEBUG_CNT_PM_LINKST_IN_L2 0x01E0EC04
|
||||
#define QCA6390_PCIE_PCIE_PARF_DEBUG_CNT_PM_LINKST_IN_L1 0x01E0EC0C
|
||||
#define QCA6390_PCIE_PCIE_PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L1 0x01E0EC84
|
||||
#define QCA6390_PCIE_PCIE_LOCAL_REG_WCSSAON_PCIE_SR_STATUS_HIGH 0x01E030C8
|
||||
#define QCA6390_PCIE_PCIE_LOCAL_REG_WCSSAON_PCIE_SR_STATUS_LOW 0x01E030CC
|
||||
#define QCA6390_PCIE_PCIE_LOCAL_REG_WCSS_STATUS_FOR_DEBUG_HIGH 0x01E0313C
|
||||
#define QCA6390_PCIE_PCIE_LOCAL_REG_WCSS_STATUS_FOR_DEBUG_LOW 0x01E03140
|
||||
#define PEACH_PCIE_PCIE_LOCAL_REG_WCSSAON_PCIE_SR_STATUS_HIGH 0x01E03214
|
||||
#define PEACH_PCIE_PCIE_LOCAL_REG_WCSSAON_PCIE_SR_STATUS_LOW 0x01E03218
|
||||
#define PEACH_PCIE_PCIE_LOCAL_REG_WCSS_STATUS_FOR_DEBUG_HIGH 0x01E03280
|
||||
#define PEACH_PCIE_PCIE_LOCAL_REG_WCSS_STATUS_FOR_DEBUG_LOW 0x01E03284
|
||||
#define QCA6390_PCIE_PCIE_BHI_EXECENV_REG 0x01E0E228
|
||||
|
||||
#define QCA6390_GCC_DEBUG_CLK_CTL 0x001E4025C
|
||||
|
||||
#define QCA6390_WCSS_Q6SS_PUBCSR_QDSP6SS_PLL_MODE 0x00D00200
|
||||
#define QCA6390_WCSS_WFSS_PMM_WFSS_PMM_R0_PMM_CTRL 0x00B60164
|
||||
#define QCA6390_WCSS_PMM_TOP_PMU_CX_CSR 0x00B70080
|
||||
#define QCA6390_WCSS_PMM_TOP_AON_INT_RAW_STAT 0x00B700E0
|
||||
#define QCA6390_WCSS_PMM_TOP_AON_INT_EN 0x00B700D0
|
||||
#define QCA6390_WCSS_PMM_TOP_PMU_TESTBUS_STS 0x00B70020
|
||||
#define QCA6390_WCSS_PMM_TOP_PMU_TESTBUS_CTL 0x00B7001C
|
||||
#define QCA6390_WCSS_PMM_TOP_TESTBUS_STS 0x00B70028
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_SAW2_CFG 0x00DB0008
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_SAW2_CFG_MSK 0x20
|
||||
#define QCA6390_WCSS_Q6SS_PUBCSR_QDSP6SS_TEST_BUS_CTL 0x00D02000
|
||||
#define QCA6390_WCSS_Q6SS_PUBCSR_QDSP6SS_TEST_BUS_VALUE 0x00D02004
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_SAW2_SPM_STS 0x00DB000C
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_SAW2_SPM_CTL 0x00DB0030
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_SAW2_SPM_SLP_SEQ_ENTRY_0 0x00DB0400
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_SAW2_SPM_SLP_SEQ_ENTRY_9 0x00DB0424
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_STATUS0 0x00D90380
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_STATUS1 0x00D90384
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_STATUS2 0x00D90388
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_STATUS3 0x00D9038C
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_STATUS4 0x00D90390
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_STATUS5 0x00D90394
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_STATUS6 0x00D90398
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_ENABLE0 0x00D90100
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_ENABLE1 0x00D90104
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_ENABLE2 0x00D90108
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_ENABLE3 0x00D9010C
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_ENABLE4 0x00D90110
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_ENABLE5 0x00D90114
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_ENABLE6 0x00D90118
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_PENDING0 0x00D90500
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_PENDING1 0x00D90504
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_PENDING2 0x00D90508
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_PENDING3 0x00D9050C
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_PENDING4 0x00D90510
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_PENDING5 0x00D90514
|
||||
#define QCA6390_WCSS_Q6SS_PRIVCSR_QDSP6SS_L2VIC_INT_PENDING6 0x00D90518
|
||||
#define QCA6390_WCSS_CC_WCSS_UMAC_NOC_CBCR 0x00C3029C
|
||||
#define QCA6390_WCSS_CC_WCSS_UMAC_AHB_CBCR 0x00C302BC
|
||||
#define QCA6390_WCSS_CC_WCSS_UMAC_GDSCR 0x00C30298
|
||||
#define QCA6390_WCSS_CC_WCSS_WLAN1_GDSCR 0x00C300C4
|
||||
#define QCA6390_WCSS_CC_WCSS_WLAN2_GDSCR 0x00C30138
|
||||
#define QCA6390_WCSS_PMM_TOP_PMM_INT_CLR 0x00B70168
|
||||
#define QCA6390_WCSS_PMM_TOP_AON_INT_STICKY_EN 0x00B700D8
|
||||
|
||||
#define QCA6390_TLMM_GPIO_IN_OUT57 0x01839004
|
||||
#define QCA6390_TLMM_GPIO_INTR_CFG57 0x01839008
|
||||
#define QCA6390_TLMM_GPIO_INTR_STATUS57 0x0183900C
|
||||
#define QCA6390_TLMM_GPIO_IN_OUT59 0x0183b004
|
||||
#define QCA6390_TLMM_GPIO_INTR_CFG59 0x0183b008
|
||||
#define QCA6390_TLMM_GPIO_INTR_STATUS59 0x0183b00C
|
||||
|
||||
#define QCA6390_WFSS_PMM_WFSS_PMM_R0_WLAN1_STATUS_REG2 0x00B6017C
|
||||
#define QCA6390_WFSS_PMM_WFSS_PMM_R0_WLAN2_STATUS_REG2 0x00B60190
|
||||
#define QCA6390_WFSS_PMM_WFSS_PMM_R0_PMM_WLAN2_CFG_REG1 0x00B6018C
|
||||
#define QCA6390_WFSS_PMM_WFSS_PMM_R0_PMM_WLAN1_CFG_REG1 0x00B60178
|
||||
#define QCA6390_WFSS_PMM_WFSS_PMM_R0_WLAN2_APS_STATUS_REG1 0x00B600B0
|
||||
#define QCA6390_WFSS_PMM_WFSS_PMM_R0_WLAN1_APS_STATUS_REG1 0x00B60044
|
||||
|
||||
#define WLAON_SOC_POWER_CTRL 0x01F80000
|
||||
#define WLAON_SOC_PWR_WDG_BARK_THRSHD 0x1F80004
|
||||
#define WLAON_SOC_PWR_WDG_BITE_THRSHD 0x1F80008
|
||||
#define WLAON_SW_COLD_RESET 0x1F8000C
|
||||
#define WLAON_RFA_MEM_SLP_NRET_N_OVERRIDE 0x1F8001C
|
||||
#define WLAON_GDSC_DELAY_SETTING 0x1F80024
|
||||
#define WLAON_GDSC_DELAY_SETTING2 0x1F80028
|
||||
#define WLAON_WL_PWR_STATUS_REG 0x1F8002C
|
||||
#define WLAON_WL_AON_DBG_CFG_REG 0x1F80030
|
||||
#define WLAON_WL_AON_DBG_ENABLE_GRP0_REG 0x1F80034
|
||||
#define WLAON_WL_AON_DBG_ENABLE_GRP1_REG 0x1F80038
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL0 0x1F80040
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL1 0x1F80044
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL2 0x1F80048
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL3 0x1F8004C
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL4 0x1F80050
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL5 0x1F80054
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL5_1 0x1F80058
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL6 0x1F8005C
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL6_1 0x1F80060
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL7 0x1F80064
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL8 0x1F80068
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL8_1 0x1F8006C
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL9 0x1F80070
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL9_1 0x1F80074
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL10 0x1F80078
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL11 0x1F8007C
|
||||
#define WLAON_WL_AON_APM_CFG_CTRL12 0x1F80080
|
||||
#define WLAON_WL_AON_APM_OVERRIDE_REG 0x1F800B0
|
||||
#define WLAON_WL_AON_CXPC_REG 0x1F800B4
|
||||
#define WLAON_WL_AON_APM_STATUS0 0x1F800C0
|
||||
#define WLAON_WL_AON_APM_STATUS1 0x1F800C4
|
||||
#define WLAON_WL_AON_APM_STATUS2 0x1F800C8
|
||||
#define WLAON_WL_AON_APM_STATUS3 0x1F800CC
|
||||
#define WLAON_WL_AON_APM_STATUS4 0x1F800D0
|
||||
#define WLAON_WL_AON_APM_STATUS5 0x1F800D4
|
||||
#define WLAON_WL_AON_APM_STATUS6 0x1F800D8
|
||||
#define WLAON_GLOBAL_COUNTER_CTRL1 0x1F80100
|
||||
#define WLAON_GLOBAL_COUNTER_CTRL6 0x1F80108
|
||||
#define WLAON_GLOBAL_COUNTER_CTRL7 0x1F8010C
|
||||
#define WLAON_GLOBAL_COUNTER_CTRL3 0x1F80118
|
||||
#define WLAON_GLOBAL_COUNTER_CTRL4 0x1F8011C
|
||||
#define WLAON_GLOBAL_COUNTER_CTRL5 0x1F80120
|
||||
#define WLAON_GLOBAL_COUNTER_CTRL8 0x1F801F0
|
||||
#define WLAON_GLOBAL_COUNTER_CTRL2 0x1F801F4
|
||||
#define WLAON_GLOBAL_COUNTER_CTRL9 0x1F801F8
|
||||
#define WLAON_RTC_CLK_CAL_CTRL1 0x1F80200
|
||||
#define WLAON_RTC_CLK_CAL_CTRL2 0x1F80204
|
||||
#define WLAON_RTC_CLK_CAL_CTRL3 0x1F80208
|
||||
#define WLAON_RTC_CLK_CAL_CTRL4 0x1F8020C
|
||||
#define WLAON_RTC_CLK_CAL_CTRL5 0x1F80210
|
||||
#define WLAON_RTC_CLK_CAL_CTRL6 0x1F80214
|
||||
#define WLAON_RTC_CLK_CAL_CTRL7 0x1F80218
|
||||
#define WLAON_RTC_CLK_CAL_CTRL8 0x1F8021C
|
||||
#define WLAON_RTC_CLK_CAL_CTRL9 0x1F80220
|
||||
#define WLAON_WCSSAON_CONFIG_REG 0x1F80300
|
||||
#define WLAON_WLAN_OEM_DEBUG_REG 0x1F80304
|
||||
#define WLAON_WLAN_RAM_DUMP_REG 0x1F80308
|
||||
#define WLAON_QDSS_WCSS_REG 0x1F8030C
|
||||
#define WLAON_QDSS_WCSS_ACK 0x1F80310
|
||||
#define WLAON_WL_CLK_CNTL_KDF_REG 0x1F80314
|
||||
#define WLAON_WL_CLK_CNTL_PMU_HFRC_REG 0x1F80318
|
||||
#define WLAON_QFPROM_PWR_CTRL_REG 0x1F8031C
|
||||
#define QFPROM_PWR_CTRL_VDD4BLOW_SW_EN_MASK 0x4
|
||||
#define QFPROM_PWR_CTRL_SHUTDOWN_EN_MASK 0x1
|
||||
#define WLAON_DLY_CONFIG 0x1F80400
|
||||
#define WLAON_WLAON_Q6_IRQ_REG 0x1F80404
|
||||
#define WLAON_PCIE_INTF_SW_CFG_REG 0x1F80408
|
||||
#define WLAON_PCIE_INTF_STICKY_SW_CFG_REG 0x1F8040C
|
||||
#define WLAON_PCIE_INTF_PHY_SW_CFG_REG 0x1F80410
|
||||
#define WLAON_PCIE_INTF_PHY_NOCSR_SW_CFG_REG 0x1F80414
|
||||
#define WLAON_Q6_COOKIE_BIT 0x1F80500
|
||||
#define WLAON_WARM_SW_ENTRY 0x1F80504
|
||||
#define WLAON_RESET_DBG_SW_ENTRY 0x1F80508
|
||||
#define WLAON_WL_PMUNOC_CFG_REG 0x1F8050C
|
||||
#define WLAON_RESET_CAUSE_CFG_REG 0x1F80510
|
||||
#define WLAON_SOC_RESET_CAUSE_SHADOW_REG 0x1F80608
|
||||
#define WLAON_SOC_WCSSAON_WAKEUP_IRQ_7_EN_REG 0x1F80514
|
||||
#define WLAON_DEBUG 0x1F80600
|
||||
#define WLAON_SOC_PARAMETERS 0x1F80604
|
||||
#define WLAON_WLPM_SIGNAL 0x1F80608
|
||||
#define WLAON_SOC_RESET_CAUSE_REG 0x1F8060C
|
||||
#define WLAON_WAKEUP_PCIE_SOC_REG 0x1F80610
|
||||
#define WLAON_PBL_STACK_CANARY 0x1F80614
|
||||
#define WLAON_MEM_TOT_NUM_GRP_REG 0x1F80618
|
||||
#define WLAON_MEM_TOT_BANKS_IN_GRP0_REG 0x1F8061C
|
||||
#define WLAON_MEM_TOT_BANKS_IN_GRP1_REG 0x1F80620
|
||||
#define WLAON_MEM_TOT_BANKS_IN_GRP2_REG 0x1F80624
|
||||
#define WLAON_MEM_TOT_BANKS_IN_GRP3_REG 0x1F80628
|
||||
#define WLAON_MEM_TOT_SIZE_IN_GRP0_REG 0x1F8062C
|
||||
#define WLAON_MEM_TOT_SIZE_IN_GRP1_REG 0x1F80630
|
||||
#define WLAON_MEM_TOT_SIZE_IN_GRP2_REG 0x1F80634
|
||||
#define WLAON_MEM_TOT_SIZE_IN_GRP3_REG 0x1F80638
|
||||
#define WLAON_MEM_SLP_NRET_OVERRIDE_GRP0_REG 0x1F8063C
|
||||
#define WLAON_MEM_SLP_NRET_OVERRIDE_GRP1_REG 0x1F80640
|
||||
#define WLAON_MEM_SLP_NRET_OVERRIDE_GRP2_REG 0x1F80644
|
||||
#define WLAON_MEM_SLP_NRET_OVERRIDE_GRP3_REG 0x1F80648
|
||||
#define WLAON_MEM_SLP_RET_OVERRIDE_GRP0_REG 0x1F8064C
|
||||
#define WLAON_MEM_SLP_RET_OVERRIDE_GRP1_REG 0x1F80650
|
||||
#define WLAON_MEM_SLP_RET_OVERRIDE_GRP2_REG 0x1F80654
|
||||
#define WLAON_MEM_SLP_RET_OVERRIDE_GRP3_REG 0x1F80658
|
||||
#define WLAON_MEM_CNT_SEL_REG 0x1F8065C
|
||||
#define WLAON_MEM_NO_EXTBHS_REG 0x1F80660
|
||||
#define WLAON_MEM_DEBUG_REG 0x1F80664
|
||||
#define WLAON_MEM_DEBUG_BUS_REG 0x1F80668
|
||||
#define WLAON_MEM_REDUN_CFG_REG 0x1F8066C
|
||||
#define WLAON_WL_AON_SPARE2 0x1F80670
|
||||
#define WLAON_VSEL_CFG_FOR_WL_RET_DISABLE_REG 0x1F80680
|
||||
#define WLAON_BTFM_WLAN_IPC_STATUS_REG 0x1F80690
|
||||
#define WLAON_MPM_COUNTER_CHICKEN_BITS 0x1F806A0
|
||||
#define WLAON_WLPM_CHICKEN_BITS 0x1F806A4
|
||||
#define WLAON_PCIE_PHY_PWR_REG 0x1F806A8
|
||||
#define WLAON_WL_CLK_CNTL_PMU_LPO2M_REG 0x1F806AC
|
||||
#define WLAON_WL_SS_ROOT_CLK_SWITCH_REG 0x1F806B0
|
||||
#define WLAON_POWERCTRL_PMU_REG 0x1F806B4
|
||||
#define WLAON_POWERCTRL_MEM_REG 0x1F806B8
|
||||
#define WLAON_PCIE_PWR_CTRL_REG 0x01F806BC
|
||||
#define WLAON_SOC_PWR_PROFILE_REG 0x1F806C0
|
||||
#define WLAON_WCSSAON_PCIE_SR_STATUS_HI_REG 0x01F806C4
|
||||
#define WLAON_WCSSAON_PCIE_SR_STATUS_LO_REG 0x1F806C8
|
||||
#define WLAON_WCSS_TCSR_PMM_SR_STATUS_HI_REG 0x1F806CC
|
||||
#define WLAON_WCSS_TCSR_PMM_SR_STATUS_LO_REG 0x1F806D0
|
||||
#define WLAON_MEM_SVS_CFG_REG 0x1F806D4
|
||||
#define WLAON_CMN_AON_MISC_REG 0x1F806D8
|
||||
#define WLAON_INTR_STATUS 0x1F80700
|
||||
#define WLAON_INTR_ENABLE 0x1F807040
|
||||
#define WLAON_NOC_DBG_BUS_SEL_REG 0x1F80708
|
||||
#define WLAON_NOC_DBG_BUS_REG 0x1F8070C
|
||||
#define WLAON_WL_CTRL_MISC_REG 0x1F80710
|
||||
#define WLAON_DBG_STATUS0 0x1F80720
|
||||
#define WLAON_DBG_STATUS1 0x1F80724
|
||||
#define WLAON_TIMERSYNC_OFFSET_L 0x1F80730
|
||||
#define WLAON_TIMERSYNC_OFFSET_H 0x1F80734
|
||||
#define WLAON_PMU_LDO_SETTLE_REG 0x1F80740
|
||||
|
||||
#define QCA6390_SYSPM_SYSPM_PWR_STATUS 0x1F82000
|
||||
#define QCA6390_SYSPM_DBG_BTFM_AON_REG 0x1F82004
|
||||
#define QCA6390_SYSPM_DBG_BUS_SEL_REG 0x1F82008
|
||||
#define QCA6390_SYSPM_WCSSAON_SR_STATUS 0x1F8200C
|
||||
|
||||
/* PCIE SOC scratch registers, address same for QCA6390 & QCA6490*/
|
||||
#define PCIE_SCRATCH_0_SOC_PCIE_REG 0x1E04040
|
||||
#define PCIE_SCRATCH_1_SOC_PCIE_REG 0x1E04044
|
||||
#define PCIE_SCRATCH_2_SOC_PCIE_REG 0x1E0405C
|
||||
|
||||
/* PCIE BHIE DEBUG registers */
|
||||
#define PCIE_PCIE_BHIE_DEBUG_0 0x1E0E1C0
|
||||
#define PCIE_PCIE_BHIE_DEBUG_1 0x1E0E1C4
|
||||
#define PCIE_PCIE_BHIE_DEBUG_2 0x1E0E1C8
|
||||
#define PCIE_PCIE_BHIE_DEBUG_3 0x1E0E1CC
|
||||
#define PCIE_PCIE_BHIE_DEBUG_4 0x1E0E1D0
|
||||
#define PCIE_PCIE_BHIE_DEBUG_5 0x1E0E1D4
|
||||
#define PCIE_PCIE_BHIE_DEBUG_6 0x1E0E1D8
|
||||
#define PCIE_PCIE_BHIE_DEBUG_7 0x1E0E1DC
|
||||
#define PCIE_PCIE_BHIE_DEBUG_8 0x1E0E1E0
|
||||
#define PCIE_PCIE_BHIE_DEBUG_9 0x1E0E1E4
|
||||
#define PCIE_PCIE_BHIE_DEBUG_10 0x1E0E1E8
|
||||
|
||||
#define GCC_GCC_SPARE_REG_1 0x1E40310
|
||||
#define GCC_PRE_ARES_DEBUG_TIMER_VAL 0x1E40270
|
||||
|
||||
#define QCN7605_WINDOW_ENABLE_BIT 0x80000000
|
||||
#endif
|
@@ -0,0 +1,12 @@
|
||||
CONFIG_CNSS2=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
||||
CONFIG_CNSS2_QMI=y
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_BUS_AUTO_SUSPEND=y
|
||||
CONFIG_CNSS2_SSR_DRIVER_DUMP=y
|
||||
CONFIG_CNSS_HW_SECURE_DISABLE=y
|
||||
CONFIG_CNSS_HW_SECURE_SMEM=y
|
||||
CONFIG_CNSS2_SMMU_DB_SUPPORT=y
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS2_DEBUG=y
|
@@ -0,0 +1,11 @@
|
||||
CONFIG_CNSS2=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
||||
CONFIG_CNSS2_QMI=y
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_BUS_AUTO_SUSPEND=y
|
||||
CONFIG_CNSS2_SSR_DRIVER_DUMP=y
|
||||
CONFIG_CNSS_HW_SECURE_DISABLE=y
|
||||
CONFIG_CNSS_HW_SECURE_SMEM=y
|
||||
CONFIG_CNSS2_SMMU_DB_SUPPORT=y
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
@@ -0,0 +1,14 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
config CNSS_GENL
|
||||
tristate "CNSS Generic Netlink Socket Driver"
|
||||
help
|
||||
This module creates generic netlink family "CLD80211". This can be
|
||||
used by cld driver and userspace utilities to communicate over
|
||||
netlink sockets. This module creates different multicast groups to
|
||||
facilitate the same.
|
||||
|
||||
config CNSS_OUT_OF_TREE
|
||||
bool "Build module out-of-tree"
|
||||
help
|
||||
This enables building the module out of the main kernel tree
|
@@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
ccflags-y += -Wmissing-prototypes
|
||||
|
||||
ifeq ($(CONFIG_CNSS_OUT_OF_TREE),y)
|
||||
ccflags-y += -I$(WLAN_PLATFORM_ROOT)/inc
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_CNSS_GENL) := cnss_nl.o
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,255 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <net/genetlink.h>
|
||||
#ifdef CONFIG_CNSS_OUT_OF_TREE
|
||||
#include "cnss_nl.h"
|
||||
#else
|
||||
#include <net/cnss_nl.h>
|
||||
#endif
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#define CLD80211_GENL_NAME "cld80211"
|
||||
|
||||
#define CLD80211_MULTICAST_GROUP_SVC_MSGS "svc_msgs"
|
||||
#define CLD80211_MULTICAST_GROUP_HOST_LOGS "host_logs"
|
||||
#define CLD80211_MULTICAST_GROUP_FW_LOGS "fw_logs"
|
||||
#define CLD80211_MULTICAST_GROUP_PER_PKT_STATS "per_pkt_stats"
|
||||
#define CLD80211_MULTICAST_GROUP_DIAG_EVENTS "diag_events"
|
||||
#define CLD80211_MULTICAST_GROUP_FATAL_EVENTS "fatal_events"
|
||||
#define CLD80211_MULTICAST_GROUP_OEM_MSGS "oem_msgs"
|
||||
|
||||
static const struct genl_multicast_group nl_mcgrps[] = {
|
||||
[CLD80211_MCGRP_SVC_MSGS] = { .name =
|
||||
CLD80211_MULTICAST_GROUP_SVC_MSGS},
|
||||
[CLD80211_MCGRP_HOST_LOGS] = { .name =
|
||||
CLD80211_MULTICAST_GROUP_HOST_LOGS},
|
||||
[CLD80211_MCGRP_FW_LOGS] = { .name =
|
||||
CLD80211_MULTICAST_GROUP_FW_LOGS},
|
||||
[CLD80211_MCGRP_PER_PKT_STATS] = { .name =
|
||||
CLD80211_MULTICAST_GROUP_PER_PKT_STATS},
|
||||
[CLD80211_MCGRP_DIAG_EVENTS] = { .name =
|
||||
CLD80211_MULTICAST_GROUP_DIAG_EVENTS},
|
||||
[CLD80211_MCGRP_FATAL_EVENTS] = { .name =
|
||||
CLD80211_MULTICAST_GROUP_FATAL_EVENTS},
|
||||
[CLD80211_MCGRP_OEM_MSGS] = { .name =
|
||||
CLD80211_MULTICAST_GROUP_OEM_MSGS},
|
||||
};
|
||||
|
||||
struct cld_ops {
|
||||
cld80211_cb cb;
|
||||
void *cb_ctx;
|
||||
};
|
||||
|
||||
struct cld80211_nl_data {
|
||||
struct cld_ops cld_ops[CLD80211_MAX_COMMANDS];
|
||||
};
|
||||
|
||||
static struct cld80211_nl_data nl_data;
|
||||
|
||||
static inline struct cld80211_nl_data *get_local_ctx(void)
|
||||
{
|
||||
return &nl_data;
|
||||
}
|
||||
|
||||
static struct genl_ops nl_ops[CLD80211_MAX_COMMANDS];
|
||||
|
||||
/* policy for the attributes */
|
||||
static const struct nla_policy cld80211_policy[CLD80211_ATTR_MAX + 1] = {
|
||||
[CLD80211_ATTR_VENDOR_DATA] = { .type = NLA_NESTED },
|
||||
[CLD80211_ATTR_DATA] = { .type = NLA_BINARY,
|
||||
.len = CLD80211_MAX_NL_DATA },
|
||||
[CLD80211_ATTR_META_DATA] = { .type = NLA_BINARY,
|
||||
.len = CLD80211_MAX_NL_DATA },
|
||||
[CLD80211_ATTR_CMD] = { .type = NLA_U32 },
|
||||
[CLD80211_ATTR_CMD_TAG_DATA] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 2, 0))
|
||||
static int cld80211_pre_doit(const struct genl_split_ops *ops,
|
||||
struct sk_buff *skb,
|
||||
struct genl_info *info)
|
||||
{
|
||||
u8 cmd_id = ops->cmd;
|
||||
struct cld80211_nl_data *nl = get_local_ctx();
|
||||
|
||||
if (cmd_id < 1 || cmd_id > CLD80211_MAX_COMMANDS) {
|
||||
pr_err("CLD80211: Command Not supported: %u\n", cmd_id);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
info->user_ptr[0] = nl->cld_ops[cmd_id - 1].cb;
|
||||
info->user_ptr[1] = nl->cld_ops[cmd_id - 1].cb_ctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int cld80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
|
||||
struct genl_info *info)
|
||||
{
|
||||
u8 cmd_id = ops->cmd;
|
||||
struct cld80211_nl_data *nl = get_local_ctx();
|
||||
|
||||
if (cmd_id < 1 || cmd_id > CLD80211_MAX_COMMANDS) {
|
||||
pr_err("CLD80211: Command Not supported: %u\n", cmd_id);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
info->user_ptr[0] = nl->cld_ops[cmd_id - 1].cb;
|
||||
info->user_ptr[1] = nl->cld_ops[cmd_id - 1].cb_ctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
/* The netlink family */
|
||||
static struct genl_family cld80211_fam __ro_after_init = {
|
||||
.name = CLD80211_GENL_NAME,
|
||||
.hdrsize = 0, /* no private header */
|
||||
.version = 1, /* no particular meaning now */
|
||||
.maxattr = CLD80211_ATTR_MAX,
|
||||
.policy = cld80211_policy,
|
||||
.netnsok = true,
|
||||
.pre_doit = cld80211_pre_doit,
|
||||
.post_doit = NULL,
|
||||
.module = THIS_MODULE,
|
||||
.ops = nl_ops,
|
||||
.n_ops = ARRAY_SIZE(nl_ops),
|
||||
.mcgrps = nl_mcgrps,
|
||||
.n_mcgrps = ARRAY_SIZE(nl_mcgrps),
|
||||
};
|
||||
|
||||
int register_cld_cmd_cb(u8 cmd_id, cld80211_cb func, void *cb_ctx)
|
||||
{
|
||||
struct cld80211_nl_data *nl = get_local_ctx();
|
||||
|
||||
pr_debug("CLD80211: Registering command: %d\n", cmd_id);
|
||||
if (!cmd_id || cmd_id > CLD80211_MAX_COMMANDS) {
|
||||
pr_debug("CLD80211: invalid command: %d\n", cmd_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nl->cld_ops[cmd_id - 1].cb = func;
|
||||
nl->cld_ops[cmd_id - 1].cb_ctx = cb_ctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(register_cld_cmd_cb);
|
||||
|
||||
int deregister_cld_cmd_cb(u8 cmd_id)
|
||||
{
|
||||
struct cld80211_nl_data *nl = get_local_ctx();
|
||||
|
||||
pr_debug("CLD80211: De-registering command: %d\n", cmd_id);
|
||||
if (!cmd_id || cmd_id > CLD80211_MAX_COMMANDS) {
|
||||
pr_debug("CLD80211: invalid command: %d\n", cmd_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nl->cld_ops[cmd_id - 1].cb = NULL;
|
||||
nl->cld_ops[cmd_id - 1].cb_ctx = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(deregister_cld_cmd_cb);
|
||||
|
||||
struct genl_family *cld80211_get_genl_family(void)
|
||||
{
|
||||
return &cld80211_fam;
|
||||
}
|
||||
EXPORT_SYMBOL(cld80211_get_genl_family);
|
||||
|
||||
static int cld80211_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
cld80211_cb cld_cb;
|
||||
void *cld_ctx;
|
||||
|
||||
cld_cb = info->user_ptr[0];
|
||||
|
||||
if (!cld_cb) {
|
||||
pr_err("CLD80211: Not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
cld_ctx = info->user_ptr[1];
|
||||
|
||||
if (info->attrs[CLD80211_ATTR_VENDOR_DATA]) {
|
||||
cld_cb(nla_data(info->attrs[CLD80211_ATTR_VENDOR_DATA]),
|
||||
nla_len(info->attrs[CLD80211_ATTR_VENDOR_DATA]),
|
||||
cld_ctx, info->snd_portid);
|
||||
} else {
|
||||
pr_err("CLD80211: No CLD80211_ATTR_VENDOR_DATA\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cld80211_init(void)
|
||||
{
|
||||
int err, i;
|
||||
|
||||
memset(&nl_ops[0], 0, sizeof(nl_ops));
|
||||
|
||||
pr_info("CLD80211: Initializing\n");
|
||||
for (i = 0; i < CLD80211_MAX_COMMANDS; i++) {
|
||||
nl_ops[i].cmd = i + 1;
|
||||
nl_ops[i].doit = cld80211_doit;
|
||||
nl_ops[i].flags = GENL_ADMIN_PERM;
|
||||
}
|
||||
|
||||
err = genl_register_family(&cld80211_fam);
|
||||
if (err) {
|
||||
pr_err("CLD80211: Failed to register cld80211 family: %d\n",
|
||||
err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __cld80211_exit(void)
|
||||
{
|
||||
genl_unregister_family(&cld80211_fam);
|
||||
}
|
||||
|
||||
/**
|
||||
* cld80211_is_valid_dt_node_found - Check if valid device tree node present
|
||||
*
|
||||
* Valid device tree node means a node with "qcom,wlan" property present and
|
||||
* "status" property not disabled.
|
||||
*
|
||||
* Return: true if valid device tree node found, false if not found
|
||||
*/
|
||||
static bool cld80211_is_valid_dt_node_found(void)
|
||||
{
|
||||
struct device_node *dn = NULL;
|
||||
|
||||
for_each_node_with_property(dn, "qcom,wlan") {
|
||||
if (of_device_is_available(dn))
|
||||
break;
|
||||
}
|
||||
|
||||
if (dn)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int __init cld80211_init(void)
|
||||
{
|
||||
if (!cld80211_is_valid_dt_node_found())
|
||||
return -ENODEV;
|
||||
|
||||
return __cld80211_init();
|
||||
}
|
||||
|
||||
static void __exit cld80211_exit(void)
|
||||
{
|
||||
__cld80211_exit();
|
||||
}
|
||||
|
||||
module_init(cld80211_init);
|
||||
module_exit(cld80211_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("CNSS generic netlink module");
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,14 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
config WCNSS_MEM_PRE_ALLOC
|
||||
tristate "WCNSS pre-alloc memory support"
|
||||
help
|
||||
Pre-allocate memory for the WLAN driver module.
|
||||
This feature enable cld wlan driver to use pre allocated memory
|
||||
for it's internal usage and release it to back to pre allocated pool.
|
||||
This memory is allocated at the cold boot time.
|
||||
|
||||
config CNSS_OUT_OF_TREE
|
||||
bool "Build module out-of-tree"
|
||||
help
|
||||
This enables building the module out of the main kernel tree
|
@@ -0,0 +1,10 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
ccflags-y += -Wmissing-prototypes
|
||||
|
||||
ifeq ($(CONFIG_CNSS_OUT_OF_TREE),y)
|
||||
ccflags-y += -I$(WLAN_PLATFORM_ROOT)/inc
|
||||
ccflags-y += -I$(WLAN_PLATFORM_ROOT)/cnss_utils
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += cnss_prealloc.o
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,406 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2012,2014-2017,2019-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mempool.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/version.h>
|
||||
#include "cnss_common.h"
|
||||
#ifdef CONFIG_CNSS_OUT_OF_TREE
|
||||
#include "cnss_prealloc.h"
|
||||
#else
|
||||
#include <net/cnss_prealloc.h>
|
||||
#endif
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0))
|
||||
/* Ideally header should be from standard include path. So this is not an
|
||||
* ideal way of header inclusion but use of slab struct to derive cache
|
||||
* from a mem ptr helps in avoiding additional tracking and/or adding headroom
|
||||
* of 8 bytes for cache in the beginning of buffer and wasting extra memory,
|
||||
* particulary in the case when size of memory requested falls around the edge
|
||||
* of a page boundary. We also have precedence of minidump_memory.c which
|
||||
* includes mm/slab.h using this style.
|
||||
*/
|
||||
#include "../mm/slab.h"
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("CNSS prealloc driver");
|
||||
|
||||
/* cnss preallocation scheme is a memory pool that always tries to keep a
|
||||
* list of free memory for use in emergencies. It is implemented on kernel
|
||||
* features: memorypool and kmem cache.
|
||||
*/
|
||||
|
||||
struct cnss_pool {
|
||||
size_t size;
|
||||
int min;
|
||||
const char name[50];
|
||||
mempool_t *mp;
|
||||
struct kmem_cache *cache;
|
||||
};
|
||||
|
||||
/**
|
||||
* Memory pool
|
||||
* -----------
|
||||
*
|
||||
* How to update this table:
|
||||
*
|
||||
* 1. Add a new row with following elements
|
||||
* size : Size of one allocation unit in bytes.
|
||||
* min : Minimum units to be reserved. Used only if a regular
|
||||
* allocation fails.
|
||||
* name : Name of the cache/pool. Will be displayed in /proc/slabinfo
|
||||
* if not merged with another pool.
|
||||
* mp : A pointer to memory pool. Updated during init.
|
||||
* cache : A pointer to cache. Updated during init.
|
||||
* 2. Always keep the table in increasing order
|
||||
* 3. Please keep the reserve pool as minimum as possible as it's always
|
||||
* preallocated.
|
||||
* 4. Always profile with different use cases after updating this table.
|
||||
* 5. A dynamic view of this pool can be viewed at /proc/slabinfo.
|
||||
* 6. Each pool has a sys node at /sys/kernel/slab/<name>
|
||||
*
|
||||
*/
|
||||
|
||||
/* size, min pool reserve, name, memorypool handler, cache handler*/
|
||||
static struct cnss_pool cnss_pools_default[] = {
|
||||
{8 * 1024, 16, "cnss-pool-8k", NULL, NULL},
|
||||
{16 * 1024, 16, "cnss-pool-16k", NULL, NULL},
|
||||
{32 * 1024, 22, "cnss-pool-32k", NULL, NULL},
|
||||
{64 * 1024, 38, "cnss-pool-64k", NULL, NULL},
|
||||
{128 * 1024, 10, "cnss-pool-128k", NULL, NULL},
|
||||
};
|
||||
|
||||
static struct cnss_pool cnss_pools_adrastea[] = {
|
||||
{8 * 1024, 2, "cnss-pool-8k", NULL, NULL},
|
||||
{16 * 1024, 10, "cnss-pool-16k", NULL, NULL},
|
||||
{32 * 1024, 8, "cnss-pool-32k", NULL, NULL},
|
||||
{64 * 1024, 4, "cnss-pool-64k", NULL, NULL},
|
||||
{128 * 1024, 2, "cnss-pool-128k", NULL, NULL},
|
||||
};
|
||||
|
||||
static struct cnss_pool cnss_pools_wcn6750[] = {
|
||||
{8 * 1024, 2, "cnss-pool-8k", NULL, NULL},
|
||||
{16 * 1024, 8, "cnss-pool-16k", NULL, NULL},
|
||||
{32 * 1024, 11, "cnss-pool-32k", NULL, NULL},
|
||||
{64 * 1024, 15, "cnss-pool-64k", NULL, NULL},
|
||||
{128 * 1024, 4, "cnss-pool-128k", NULL, NULL},
|
||||
};
|
||||
|
||||
struct cnss_pool *cnss_pools;
|
||||
unsigned int cnss_prealloc_pool_size = ARRAY_SIZE(cnss_pools_default);
|
||||
|
||||
/**
|
||||
* cnss_pool_alloc_threshold() - Allocation threshold
|
||||
*
|
||||
* Minimum memory size to be part of cnss pool.
|
||||
*
|
||||
* Return: Size
|
||||
*
|
||||
*/
|
||||
static inline size_t cnss_pool_alloc_threshold(void)
|
||||
{
|
||||
return cnss_pools[0].size;
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_pool_int() - Initialize memory pools.
|
||||
*
|
||||
* Create cnss pools as configured by cnss_pools[]. It is the responsibility of
|
||||
* the caller to invoke cnss_pool_deinit() routine to clean it up. This
|
||||
* function needs to be called at early boot to preallocate minimum buffers in
|
||||
* the pool.
|
||||
*
|
||||
* Return: 0 - success, otherwise error code.
|
||||
*
|
||||
*/
|
||||
static int cnss_pool_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cnss_prealloc_pool_size; i++) {
|
||||
/* Create the slab cache */
|
||||
cnss_pools[i].cache =
|
||||
kmem_cache_create_usercopy(cnss_pools[i].name,
|
||||
cnss_pools[i].size, 0,
|
||||
SLAB_ACCOUNT, 0,
|
||||
cnss_pools[i].size, NULL);
|
||||
if (!cnss_pools[i].cache) {
|
||||
pr_err("cnss_prealloc: cache %s failed\n",
|
||||
cnss_pools[i].name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Create the pool and associate to slab cache */
|
||||
cnss_pools[i].mp =
|
||||
mempool_create(cnss_pools[i].min, mempool_alloc_slab,
|
||||
mempool_free_slab, cnss_pools[i].cache);
|
||||
|
||||
if (!cnss_pools[i].mp) {
|
||||
pr_err("cnss_prealloc: mempool %s failed\n",
|
||||
cnss_pools[i].name);
|
||||
kmem_cache_destroy(cnss_pools[i].cache);
|
||||
cnss_pools[i].cache = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
pr_info("cnss_prealloc: created mempool %s of min size %d * %zu\n",
|
||||
cnss_pools[i].name, cnss_pools[i].min,
|
||||
cnss_pools[i].size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_pool_deinit() - Free memory pools.
|
||||
*
|
||||
* Free the memory pools and return resources back to the system. It warns
|
||||
* if there is any pending element in memory pool or cache.
|
||||
*
|
||||
*/
|
||||
static void cnss_pool_deinit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!cnss_pools)
|
||||
return;
|
||||
|
||||
for (i = 0; i < cnss_prealloc_pool_size; i++) {
|
||||
pr_info("cnss_prealloc: destroy mempool %s\n",
|
||||
cnss_pools[i].name);
|
||||
mempool_destroy(cnss_pools[i].mp);
|
||||
kmem_cache_destroy(cnss_pools[i].cache);
|
||||
cnss_pools[i].mp = NULL;
|
||||
cnss_pools[i].cache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void cnss_assign_prealloc_pool(unsigned long device_id)
|
||||
{
|
||||
pr_info("cnss_prealloc: assign cnss pool for device id 0x%lx", device_id);
|
||||
|
||||
switch (device_id) {
|
||||
case ADRASTEA_DEVICE_ID:
|
||||
cnss_pools = cnss_pools_adrastea;
|
||||
cnss_prealloc_pool_size = ARRAY_SIZE(cnss_pools_adrastea);
|
||||
break;
|
||||
case WCN6750_DEVICE_ID:
|
||||
cnss_pools = cnss_pools_wcn6750;
|
||||
cnss_prealloc_pool_size = ARRAY_SIZE(cnss_pools_wcn6750);
|
||||
break;
|
||||
case WCN6450_DEVICE_ID:
|
||||
case QCA6390_DEVICE_ID:
|
||||
case QCA6490_DEVICE_ID:
|
||||
case MANGO_DEVICE_ID:
|
||||
case PEACH_DEVICE_ID:
|
||||
case KIWI_DEVICE_ID:
|
||||
default:
|
||||
cnss_pools = cnss_pools_default;
|
||||
cnss_prealloc_pool_size = ARRAY_SIZE(cnss_pools_default);
|
||||
}
|
||||
}
|
||||
|
||||
void cnss_initialize_prealloc_pool(unsigned long device_id)
|
||||
{
|
||||
cnss_assign_prealloc_pool(device_id);
|
||||
cnss_pool_init();
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_initialize_prealloc_pool);
|
||||
|
||||
void cnss_deinitialize_prealloc_pool(void)
|
||||
{
|
||||
cnss_pool_deinit();
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_deinitialize_prealloc_pool);
|
||||
|
||||
/**
|
||||
* cnss_pool_get_index() - Get the index of memory pool
|
||||
* @mem: Allocated memory
|
||||
*
|
||||
* Returns the index of the memory pool which fits the reqested memory. The
|
||||
* complexity of this check is O(num of memory pools). Returns a negative
|
||||
* value with error code in case of failure.
|
||||
*
|
||||
*/
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0))
|
||||
static int cnss_pool_get_index(void *mem)
|
||||
{
|
||||
struct slab *slab;
|
||||
struct kmem_cache *cache;
|
||||
int i;
|
||||
|
||||
if (!virt_addr_valid(mem))
|
||||
return -EINVAL;
|
||||
|
||||
/* mem -> slab -> cache */
|
||||
slab = virt_to_slab(mem);
|
||||
if (!slab)
|
||||
return -ENOENT;
|
||||
|
||||
cache = slab->slab_cache;
|
||||
if (!cache)
|
||||
return -ENOENT;
|
||||
|
||||
/* Check if memory belongs to a pool */
|
||||
for (i = 0; i < cnss_prealloc_pool_size; i++) {
|
||||
if (cnss_pools[i].cache == cache)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)) */
|
||||
static int cnss_pool_get_index(void *mem)
|
||||
{
|
||||
struct page *page;
|
||||
struct kmem_cache *cache;
|
||||
int i;
|
||||
|
||||
if (!virt_addr_valid(mem))
|
||||
return -EINVAL;
|
||||
|
||||
/* mem -> page -> cache */
|
||||
page = virt_to_head_page(mem);
|
||||
if (!page)
|
||||
return -ENOENT;
|
||||
|
||||
cache = page->slab_cache;
|
||||
if (!cache)
|
||||
return -ENOENT;
|
||||
|
||||
/* Check if memory belongs to a pool */
|
||||
for (i = 0; i < cnss_prealloc_pool_size; i++) {
|
||||
if (cnss_pools[i].cache == cache)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)) */
|
||||
|
||||
/**
|
||||
* wcnss_prealloc_get() - Get preallocated memory from a pool
|
||||
* @size: Size to allocate
|
||||
*
|
||||
* Memory pool is chosen based on the size. If memory is not available in a
|
||||
* given pool it goes to next higher sized pool until it succeeds.
|
||||
*
|
||||
* Return: A void pointer to allocated memory
|
||||
*/
|
||||
void *wcnss_prealloc_get(size_t size)
|
||||
{
|
||||
|
||||
void *mem = NULL;
|
||||
gfp_t gfp_mask = __GFP_ZERO;
|
||||
int i;
|
||||
|
||||
if (!cnss_pools)
|
||||
return mem;
|
||||
|
||||
if (in_interrupt() || !preemptible() || rcu_preempt_depth())
|
||||
gfp_mask |= GFP_ATOMIC;
|
||||
else
|
||||
gfp_mask |= GFP_KERNEL;
|
||||
|
||||
if (size >= cnss_pool_alloc_threshold()) {
|
||||
|
||||
for (i = 0; i < cnss_prealloc_pool_size; i++) {
|
||||
if (cnss_pools[i].size >= size && cnss_pools[i].mp) {
|
||||
mem = mempool_alloc(cnss_pools[i].mp, gfp_mask);
|
||||
if (mem)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mem && size >= cnss_pool_alloc_threshold()) {
|
||||
pr_debug("cnss_prealloc: not available for size %zu, flag %x\n",
|
||||
size, gfp_mask);
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
EXPORT_SYMBOL(wcnss_prealloc_get);
|
||||
|
||||
/**
|
||||
* wcnss_prealloc_put() - Relase allocated memory
|
||||
* @mem: Allocated memory
|
||||
*
|
||||
* Free the memory got by wcnss_prealloc_get() to slab or pool reserve if memory
|
||||
* pool doesn't have enough elements.
|
||||
*
|
||||
* Return: 1 - success
|
||||
* 0 - fail
|
||||
*/
|
||||
int wcnss_prealloc_put(void *mem)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!mem || !cnss_pools)
|
||||
return 0;
|
||||
|
||||
i = cnss_pool_get_index(mem);
|
||||
if (i >= 0 && i < cnss_prealloc_pool_size && cnss_pools[i].mp) {
|
||||
mempool_free(mem, cnss_pools[i].mp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(wcnss_prealloc_put);
|
||||
|
||||
/* Not implemented. Make use of Linux SLAB features. */
|
||||
void wcnss_prealloc_check_memory_leak(void) {}
|
||||
EXPORT_SYMBOL(wcnss_prealloc_check_memory_leak);
|
||||
|
||||
/* Not implemented. Make use of Linux SLAB features. */
|
||||
int wcnss_pre_alloc_reset(void) { return -EOPNOTSUPP; }
|
||||
EXPORT_SYMBOL(wcnss_pre_alloc_reset);
|
||||
|
||||
/**
|
||||
* cnss_prealloc_is_valid_dt_node_found - Check if valid device tree node
|
||||
* present
|
||||
*
|
||||
* Valid device tree node means a node with "qcom,wlan" property present
|
||||
* and "status" property not disabled.
|
||||
*
|
||||
* Return: true if valid device tree node found, false if not found
|
||||
*/
|
||||
static bool cnss_prealloc_is_valid_dt_node_found(void)
|
||||
{
|
||||
struct device_node *dn = NULL;
|
||||
|
||||
for_each_node_with_property(dn, "qcom,wlan") {
|
||||
if (of_device_is_available(dn))
|
||||
break;
|
||||
}
|
||||
|
||||
if (dn)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int __init cnss_prealloc_init(void)
|
||||
{
|
||||
if (!cnss_prealloc_is_valid_dt_node_found())
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit cnss_prealloc_exit(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(cnss_prealloc_init);
|
||||
module_exit(cnss_prealloc_exit);
|
||||
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,2 @@
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,30 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
config CNSS_UTILS
|
||||
tristate "CNSS utilities support"
|
||||
help
|
||||
Add CNSS utilities support for the WLAN driver module.
|
||||
This feature enables wlan driver to use CNSS utilities APIs to set
|
||||
and get wlan related information.
|
||||
|
||||
config CNSS_QMI_SVC
|
||||
tristate "CNSS QMI SVC support"
|
||||
help
|
||||
Add CNSS QMI SVC support for the WLAN driver module.
|
||||
This feature enable wlan driver to use CNSS QMI service APIs to set
|
||||
and get wlan related information.
|
||||
|
||||
config CNSS_PLAT_IPC_QMI_SVC
|
||||
tristate "CNSS Platform QMI IPC Support"
|
||||
help
|
||||
Add CNSS platform kernel and user space components IPC using QMI.
|
||||
|
||||
config CNSS_OUT_OF_TREE
|
||||
bool "Build module out-of-tree"
|
||||
help
|
||||
This enables building the module out of the main kernel tree
|
||||
|
||||
config FEATURE_SMEM_MAILBOX
|
||||
bool "Enable Feature SMEM Mailbox"
|
||||
default n
|
||||
|
@@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
ccflags-y += -Wmissing-prototypes
|
||||
|
||||
ifeq ($(CONFIG_CNSS_OUT_OF_TREE),y)
|
||||
ccflags-y += -I$(WLAN_PLATFORM_ROOT)/inc
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_CNSS_UTILS) += cnss_utils.o
|
||||
|
||||
obj-$(CONFIG_CNSS_QMI_SVC) += wlan_firmware_service.o
|
||||
wlan_firmware_service-y := wlan_firmware_service_v01.o device_management_service_v01.o ip_multimedia_subsystem_private_service_v01.o
|
||||
|
||||
obj-$(CONFIG_CNSS_PLAT_IPC_QMI_SVC) += cnss_plat_ipc_qmi_svc.o
|
||||
cnss_plat_ipc_qmi_svc-y := cnss_plat_ipc_qmi.o cnss_plat_ipc_service_v01.o
|
@@ -0,0 +1,4 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,4 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,25 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define QCA6174_VENDOR_ID 0x168C
|
||||
#define QCA6174_DEVICE_ID 0x003E
|
||||
#define QCA6290_VENDOR_ID 0x17CB
|
||||
#define QCA6290_DEVICE_ID 0x1100
|
||||
#define QCA6390_VENDOR_ID 0x17CB
|
||||
#define QCA6390_DEVICE_ID 0x1101
|
||||
#define QCA6490_VENDOR_ID 0x17CB
|
||||
#define QCA6490_DEVICE_ID 0x1103
|
||||
#define QCN7605_VENDOR_ID 0x17CB
|
||||
#define QCN7605_DEVICE_ID 0x1102
|
||||
#define KIWI_VENDOR_ID 0x17CB
|
||||
#define KIWI_DEVICE_ID 0x1107
|
||||
#define MANGO_VENDOR_ID 0x17CB
|
||||
#define MANGO_DEVICE_ID 0x110A
|
||||
#define PEACH_VENDOR_ID 0x17CB
|
||||
#define PEACH_DEVICE_ID 0x110E
|
||||
#define WCN6750_DEVICE_ID 0x6750
|
||||
#define WCN6450_DEVICE_ID 0x6450
|
||||
#define ADRASTEA_DEVICE_ID 0xabcd
|
@@ -0,0 +1,988 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021, 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/qrtr.h>
|
||||
#include <linux/soc/qcom/qmi.h>
|
||||
#if IS_ENABLED(CONFIG_IPC_LOGGING)
|
||||
#include <linux/ipc_logging.h>
|
||||
#endif
|
||||
#include <linux/sched.h>
|
||||
#include <asm/current.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/of.h>
|
||||
#include "cnss_plat_ipc_qmi.h"
|
||||
#include "cnss_plat_ipc_service_v01.h"
|
||||
|
||||
#define CNSS_MAX_FILE_SIZE (32 * 1024 * 1024)
|
||||
#define CNSS_PLAT_IPC_MAX_USER 1
|
||||
#define CNSS_PLAT_IPC_QMI_FILE_TXN_TIMEOUT 10000
|
||||
#define QMI_INIT_RETRY_MAX_TIMES 240
|
||||
#define QMI_INIT_RETRY_DELAY_MS 250
|
||||
#define NUM_LOG_PAGES 10
|
||||
#define CNSS_DAEMON_CFG_WAIT_RETRY 200
|
||||
#define CNSS_DAEMON_CFG_WAIT_MS 50
|
||||
|
||||
/**
|
||||
* struct cnss_plat_ipc_file_data: File transfer context data
|
||||
* @name: File name
|
||||
* @buf: Buffer provided for TX/RX file contents
|
||||
* @id: File ID corresponding to file name
|
||||
* @buf_size: Buffer size
|
||||
* @file_fize: File Size
|
||||
* @seg_index: Running index for buffer segments
|
||||
* @seg_len: Total number of segments
|
||||
* @end: End of transaction
|
||||
* @complete: Completion variable for file transfer
|
||||
*/
|
||||
struct cnss_plat_ipc_file_data {
|
||||
char *name;
|
||||
char *buf;
|
||||
u32 id;
|
||||
u32 buf_size;
|
||||
u32 file_size;
|
||||
u32 seg_index;
|
||||
u32 seg_len;
|
||||
u32 end;
|
||||
struct completion complete;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cnss_plat_ipc_qmi_client_ctx: Context for QMI IPC client
|
||||
* @client_sq: QMI IPC client QRTR socket
|
||||
* @client_connected: QMI IPC client connection status
|
||||
* @connection_update_cb: Registered user callback for QMI connection status
|
||||
* @cb_ctx: Context for registered user
|
||||
* @num_user: Number of registered users
|
||||
*/
|
||||
struct cnss_plat_ipc_qmi_client_ctx {
|
||||
struct sockaddr_qrtr client_sq;
|
||||
bool client_connected;
|
||||
|
||||
cnss_plat_ipc_connection_update
|
||||
connection_update_cb[CNSS_PLAT_IPC_MAX_USER];
|
||||
void *cb_ctx[CNSS_PLAT_IPC_MAX_USER];
|
||||
u32 num_user;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cnss_plat_ipc_qmi_svc_ctx: Platform context for QMI IPC service
|
||||
* @svc_hdl: QMI server handle
|
||||
* @file_idr: File ID generator
|
||||
* @flle_idr_lock: File ID generator usage lock
|
||||
* @qmi_client_ctx: ontext for QMI IPC client
|
||||
*/
|
||||
struct cnss_plat_ipc_qmi_svc_ctx {
|
||||
struct qmi_handle *svc_hdl;
|
||||
struct idr file_idr;
|
||||
struct mutex file_idr_lock; /* File ID generator usage lock */
|
||||
struct cnss_plat_ipc_qmi_client_ctx
|
||||
qmi_client_ctx[CNSS_PLAT_IPC_MAX_QMI_CLIENTS + 1];
|
||||
};
|
||||
|
||||
static struct cnss_plat_ipc_qmi_svc_ctx plat_ipc_qmi_svc;
|
||||
static struct cnss_plat_ipc_daemon_config daemon_cfg;
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPC_LOGGING)
|
||||
static void *cnss_plat_ipc_log_context;
|
||||
|
||||
static void cnss_plat_ipc_logging_init(void)
|
||||
{
|
||||
cnss_plat_ipc_log_context = ipc_log_context_create(NUM_LOG_PAGES,
|
||||
"cnss_plat", 0);
|
||||
if (!cnss_plat_ipc_log_context)
|
||||
pr_err("cnss_plat: Unable to create log context\n");
|
||||
}
|
||||
|
||||
static void cnss_plat_ipc_logging_deinit(void)
|
||||
{
|
||||
if (cnss_plat_ipc_log_context) {
|
||||
ipc_log_context_destroy(cnss_plat_ipc_log_context);
|
||||
cnss_plat_ipc_log_context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void cnss_plat_ipc_debug_log_print(void *log_ctx, char *process, const char *fn,
|
||||
const char *log_level, char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list va_args;
|
||||
|
||||
va_start(va_args, fmt);
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &va_args;
|
||||
|
||||
if (log_level)
|
||||
printk("%scnss_plat: %pV", log_level, &vaf);
|
||||
|
||||
ipc_log_string(log_ctx, "[%s] %s: %pV", process, fn, &vaf);
|
||||
|
||||
va_end(va_args);
|
||||
}
|
||||
|
||||
#define cnss_plat_ipc_log_print(_x...) \
|
||||
cnss_plat_ipc_debug_log_print(cnss_plat_ipc_log_context, _x)
|
||||
#else
|
||||
static void cnss_plat_ipc_logging_init(void) {};
|
||||
static void cnss_plat_ipc_logging_deinit(void) {};
|
||||
|
||||
static void cnss_plat_ipc_debug_log_print(void *log_ctx, char *process, const char *fn,
|
||||
const char *log_level, char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list va_args;
|
||||
|
||||
va_start(va_args, fmt);
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &va_args;
|
||||
|
||||
if (log_level)
|
||||
printk("%scnss_plat: %pV", log_level, &vaf);
|
||||
|
||||
va_end(va_args);
|
||||
}
|
||||
|
||||
#define cnss_plat_ipc_log_print(_x...) \
|
||||
cnss_plat_ipc_debug_log_print((void *)NULL, _x)
|
||||
#endif
|
||||
|
||||
#define proc_name (in_irq() ? "irq" : \
|
||||
(in_softirq() ? "soft_irq" : current->comm))
|
||||
#define cnss_plat_ipc_err(_fmt, ...) \
|
||||
cnss_plat_ipc_log_print(proc_name, __func__, \
|
||||
KERN_ERR, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#define cnss_plat_ipc_info(_fmt, ...) \
|
||||
cnss_plat_ipc_log_print(proc_name, __func__, \
|
||||
KERN_INFO, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#define cnss_plat_ipc_dbg(_fmt, ...) \
|
||||
cnss_plat_ipc_log_print(proc_name, __func__, \
|
||||
KERN_DEBUG, _fmt, ##__VA_ARGS__)
|
||||
/**
|
||||
* cnss_plat_ipc_init_file_data() - Initialize file transfer context data
|
||||
* @name: File name
|
||||
* @buf: Buffer pointer for file contents
|
||||
* @buf_size: Buffer size for download / upload
|
||||
* @file_size: File size for upload
|
||||
*
|
||||
* Return: File data pointer
|
||||
*/
|
||||
static
|
||||
struct cnss_plat_ipc_file_data *cnss_plat_ipc_init_file_data(char *name,
|
||||
char *buf,
|
||||
u32 buf_size,
|
||||
u32 file_size)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
struct cnss_plat_ipc_file_data *fd;
|
||||
|
||||
fd = kmalloc(sizeof(*fd), GFP_KERNEL);
|
||||
if (!fd)
|
||||
goto end;
|
||||
fd->name = name;
|
||||
fd->buf = buf;
|
||||
fd->buf_size = buf_size;
|
||||
fd->file_size = file_size;
|
||||
fd->seg_index = 0;
|
||||
fd->end = 0;
|
||||
if (file_size)
|
||||
fd->seg_len =
|
||||
(file_size / CNSS_PLAT_IPC_QMI_MAX_DATA_SIZE_V01) +
|
||||
!!(file_size % CNSS_PLAT_IPC_QMI_MAX_DATA_SIZE_V01);
|
||||
else
|
||||
fd->seg_len = 0;
|
||||
init_completion(&fd->complete);
|
||||
mutex_lock(&svc->file_idr_lock);
|
||||
fd->id = idr_alloc_cyclic(&svc->file_idr, fd, 0, U32_MAX, GFP_KERNEL);
|
||||
if (fd->id < 0) {
|
||||
kfree(fd);
|
||||
fd = NULL;
|
||||
}
|
||||
mutex_unlock(&svc->file_idr_lock);
|
||||
end:
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_deinit_file_data() - Release file transfer context data
|
||||
* @fd: File data pointer
|
||||
*
|
||||
* Return: 0 on success, negative error values otherwise
|
||||
*/
|
||||
static int cnss_plat_ipc_deinit_file_data(struct cnss_plat_ipc_file_data *fd)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(!fd))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&svc->file_idr_lock);
|
||||
idr_remove(&svc->file_idr, fd->id);
|
||||
mutex_unlock(&svc->file_idr_lock);
|
||||
|
||||
if (!fd->end)
|
||||
ret = -EINVAL;
|
||||
kfree(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_qmi_update_user() - Inform registered users about QMI
|
||||
* client status
|
||||
* @client_id: User space QMI IPC client ID. Also works as
|
||||
* array index for QMI client context
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void
|
||||
cnss_plat_ipc_qmi_update_user(enum cnss_plat_ipc_qmi_client_id_v01 client_id)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
struct cnss_plat_ipc_qmi_client_ctx *qmi_client =
|
||||
&svc->qmi_client_ctx[client_id];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < qmi_client->num_user; i++) {
|
||||
if (qmi_client->connection_update_cb[i])
|
||||
qmi_client->connection_update_cb[i]
|
||||
(qmi_client->cb_ctx[i],
|
||||
qmi_client->client_connected);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_qmi_file_upload() - Upload data as platform accessible file
|
||||
* @client_id: User space QMI IPC client ID. Also works as
|
||||
* array index for QMI client context
|
||||
* @file_mame: File name to store in platform data location
|
||||
* @file_buf: Pointer to buffer with file contents
|
||||
* @file_size: Provides the size of buffer / file size
|
||||
*
|
||||
* Return: 0 on success, negative error values otherwise
|
||||
*/
|
||||
int cnss_plat_ipc_qmi_file_upload(enum cnss_plat_ipc_qmi_client_id_v01
|
||||
client_id, char *file_name, u8 *file_buf,
|
||||
u32 file_size)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_file_upload_ind_msg_v01 ind;
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
struct cnss_plat_ipc_qmi_client_ctx *qmi_client;
|
||||
int ret;
|
||||
struct cnss_plat_ipc_file_data *fd;
|
||||
|
||||
if (client_id > CNSS_PLAT_IPC_MAX_QMI_CLIENTS) {
|
||||
cnss_plat_ipc_err("Invalid Client ID: %d\n", client_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qmi_client = &svc->qmi_client_ctx[client_id];
|
||||
|
||||
if (!qmi_client->client_connected || !file_name || !file_buf)
|
||||
return -EINVAL;
|
||||
|
||||
cnss_plat_ipc_info("File name: %s Size: %d\n", file_name, file_size);
|
||||
|
||||
if (file_size == 0 || file_size > CNSS_MAX_FILE_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
fd = cnss_plat_ipc_init_file_data(file_name, file_buf, file_size,
|
||||
file_size);
|
||||
if (!fd) {
|
||||
cnss_plat_ipc_err("Unable to initialize file transfer data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
scnprintf(ind.file_name, CNSS_PLAT_IPC_QMI_MAX_FILE_NAME_LEN_V01, "%s",
|
||||
fd->name);
|
||||
ind.file_size = fd->file_size;
|
||||
ind.file_id = fd->id;
|
||||
|
||||
ret = qmi_send_indication
|
||||
(svc->svc_hdl, &qmi_client->client_sq,
|
||||
CNSS_PLAT_IPC_QMI_FILE_UPLOAD_IND_V01,
|
||||
CNSS_PLAT_IPC_QMI_FILE_UPLOAD_IND_MSG_V01_MAX_MSG_LEN,
|
||||
cnss_plat_ipc_qmi_file_upload_ind_msg_v01_ei, &ind);
|
||||
|
||||
if (ret < 0) {
|
||||
cnss_plat_ipc_err("QMI failed: %d\n", ret);
|
||||
goto end;
|
||||
}
|
||||
ret = wait_for_completion_timeout(&fd->complete,
|
||||
msecs_to_jiffies
|
||||
(CNSS_PLAT_IPC_QMI_FILE_TXN_TIMEOUT));
|
||||
if (!ret)
|
||||
cnss_plat_ipc_err("Timeout Uploading file: %s\n", fd->name);
|
||||
|
||||
end:
|
||||
ret = cnss_plat_ipc_deinit_file_data(fd);
|
||||
cnss_plat_ipc_dbg("Status: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_qmi_file_upload);
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_qmi_file_upload_req_handler() - QMI Upload data request handler
|
||||
* @handle: Pointer to QMI handle
|
||||
* @sq: QMI socket
|
||||
* @txn: QMI transaction pointer
|
||||
* @decoded_msg: Pointer to decoded QMI message
|
||||
*
|
||||
* Handles the QMI upload sequence from userspace. It uses the file descriptor
|
||||
* ID to upload buffer contents to QMI messages as segments.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void
|
||||
cnss_plat_ipc_qmi_file_upload_req_handler(struct qmi_handle *handle,
|
||||
struct sockaddr_qrtr *sq,
|
||||
struct qmi_txn *txn,
|
||||
const void *decoded_msg)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_file_upload_req_msg_v01 *req_msg;
|
||||
struct cnss_plat_ipc_qmi_file_upload_resp_msg_v01 *resp;
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
int ret = 0;
|
||||
struct cnss_plat_ipc_file_data *fd;
|
||||
|
||||
req_msg = (struct cnss_plat_ipc_qmi_file_upload_req_msg_v01 *)
|
||||
decoded_msg;
|
||||
if (!req_msg)
|
||||
return;
|
||||
cnss_plat_ipc_dbg("File ID: %d Seg Index: %d\n", req_msg->file_id,
|
||||
req_msg->seg_index);
|
||||
|
||||
mutex_lock(&svc->file_idr_lock);
|
||||
fd = idr_find(&svc->file_idr, req_msg->file_id);
|
||||
mutex_unlock(&svc->file_idr_lock);
|
||||
if (!fd) {
|
||||
cnss_plat_ipc_err("Invalid File ID %d\n", req_msg->file_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req_msg->seg_index != fd->seg_index) {
|
||||
cnss_plat_ipc_err("File %s transfer segment failure\n", fd->name);
|
||||
complete(&fd->complete);
|
||||
}
|
||||
|
||||
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
|
||||
if (!resp)
|
||||
return;
|
||||
|
||||
resp->file_id = fd->id;
|
||||
resp->seg_index = fd->seg_index++;
|
||||
resp->seg_buf_len =
|
||||
(fd->buf_size > CNSS_PLAT_IPC_QMI_MAX_DATA_SIZE_V01 ?
|
||||
CNSS_PLAT_IPC_QMI_MAX_DATA_SIZE_V01 : fd->buf_size);
|
||||
resp->end = (fd->seg_index == fd->seg_len);
|
||||
memcpy(resp->seg_buf, fd->buf, resp->seg_buf_len);
|
||||
|
||||
cnss_plat_ipc_dbg("ID: %d Seg ID: %d Len: %d End: %d\n", resp->file_id,
|
||||
resp->seg_index, resp->seg_buf_len, resp->end);
|
||||
|
||||
ret = qmi_send_response
|
||||
(svc->svc_hdl, sq, txn,
|
||||
CNSS_PLAT_IPC_QMI_FILE_UPLOAD_RESP_V01,
|
||||
CNSS_PLAT_IPC_QMI_FILE_UPLOAD_RESP_MSG_V01_MAX_MSG_LEN,
|
||||
cnss_plat_ipc_qmi_file_upload_resp_msg_v01_ei,
|
||||
resp);
|
||||
|
||||
if (ret < 0) {
|
||||
cnss_plat_ipc_err("QMI failed: %d\n", ret);
|
||||
goto end;
|
||||
}
|
||||
|
||||
fd->buf_size -= resp->seg_buf_len;
|
||||
fd->buf += resp->seg_buf_len;
|
||||
if (resp->end) {
|
||||
fd->end = true;
|
||||
complete(&fd->complete);
|
||||
}
|
||||
end:
|
||||
kfree(resp);
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_qmi_file_download() - Download platform accessible file
|
||||
* @client_id: User space QMI IPC client ID. Also works as
|
||||
* array index for QMI client context
|
||||
* @file_mame: File name to get from platform data location
|
||||
* @buf: Pointer of the buffer to store file contents
|
||||
* @size: Provides the size of buffer. It is updated to reflect the file size
|
||||
* at the end of file download.
|
||||
*/
|
||||
int cnss_plat_ipc_qmi_file_download(enum cnss_plat_ipc_qmi_client_id_v01
|
||||
client_id, char *file_name, char *buf,
|
||||
u32 *size)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_file_download_ind_msg_v01 ind;
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
struct cnss_plat_ipc_qmi_client_ctx *qmi_client;
|
||||
int ret;
|
||||
struct cnss_plat_ipc_file_data *fd;
|
||||
|
||||
if (client_id > CNSS_PLAT_IPC_MAX_QMI_CLIENTS) {
|
||||
cnss_plat_ipc_err("Invalid Client ID: %d\n", client_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qmi_client = &svc->qmi_client_ctx[client_id];
|
||||
|
||||
if (!qmi_client->client_connected || !file_name || !buf)
|
||||
return -EINVAL;
|
||||
|
||||
fd = cnss_plat_ipc_init_file_data(file_name, buf, *size, 0);
|
||||
if (!fd) {
|
||||
cnss_plat_ipc_err("Unable to initialize file transfer data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
scnprintf(ind.file_name, CNSS_PLAT_IPC_QMI_MAX_FILE_NAME_LEN_V01, "%s",
|
||||
file_name);
|
||||
ind.file_id = fd->id;
|
||||
|
||||
ret = qmi_send_indication
|
||||
(svc->svc_hdl, &qmi_client->client_sq,
|
||||
CNSS_PLAT_IPC_QMI_FILE_DOWNLOAD_IND_V01,
|
||||
CNSS_PLAT_IPC_QMI_FILE_DOWNLOAD_IND_MSG_V01_MAX_MSG_LEN,
|
||||
cnss_plat_ipc_qmi_file_download_ind_msg_v01_ei, &ind);
|
||||
|
||||
if (ret < 0) {
|
||||
cnss_plat_ipc_err("QMI failed: %d\n", ret);
|
||||
goto end;
|
||||
}
|
||||
ret = wait_for_completion_timeout(&fd->complete,
|
||||
msecs_to_jiffies
|
||||
(CNSS_PLAT_IPC_QMI_FILE_TXN_TIMEOUT));
|
||||
if (!ret)
|
||||
cnss_plat_ipc_err("Timeout downloading file:%s\n", fd->name);
|
||||
|
||||
end:
|
||||
*size = fd->file_size;
|
||||
ret = cnss_plat_ipc_deinit_file_data(fd);
|
||||
cnss_plat_ipc_dbg("Status: %d Size: %d\n", ret, *size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_qmi_file_download);
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_qmi_file_download_req_handler() - QMI download request handler
|
||||
* @handle: Pointer to QMI handle
|
||||
* @sq: QMI socket
|
||||
* @txn: QMI transaction pointer
|
||||
* @decoded_msg: Pointer to decoded QMI message
|
||||
*
|
||||
* Handles the QMI download request sequence to userspace. It uses the file
|
||||
* descriptor ID to download QMI message buffer segment to file descriptor
|
||||
* buffer.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void
|
||||
cnss_plat_ipc_qmi_file_download_req_handler(struct qmi_handle *handle,
|
||||
struct sockaddr_qrtr *sq,
|
||||
struct qmi_txn *txn,
|
||||
const void *decoded_msg)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_file_download_req_msg_v01 *req_msg;
|
||||
struct cnss_plat_ipc_qmi_file_download_resp_msg_v01 resp = {0};
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
int ret = 0;
|
||||
struct cnss_plat_ipc_file_data *fd;
|
||||
|
||||
req_msg = (struct cnss_plat_ipc_qmi_file_download_req_msg_v01 *)
|
||||
decoded_msg;
|
||||
if (!req_msg)
|
||||
return;
|
||||
cnss_plat_ipc_dbg("File ID: %d Size: %d Seg Len: %d Index: %d End: %d\n",
|
||||
req_msg->file_id, req_msg->file_size,
|
||||
req_msg->seg_buf_len, req_msg->seg_index,
|
||||
req_msg->end);
|
||||
|
||||
mutex_lock(&svc->file_idr_lock);
|
||||
fd = idr_find(&svc->file_idr, req_msg->file_id);
|
||||
mutex_unlock(&svc->file_idr_lock);
|
||||
if (!fd) {
|
||||
cnss_plat_ipc_err("Invalid File ID: %d\n", req_msg->file_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req_msg->file_size > fd->buf_size) {
|
||||
cnss_plat_ipc_err("File %s size %d larger than buffer size %d\n",
|
||||
fd->name, req_msg->file_size, fd->buf_size);
|
||||
goto file_error;
|
||||
}
|
||||
if (req_msg->seg_buf_len > CNSS_PLAT_IPC_QMI_MAX_DATA_SIZE_V01 ||
|
||||
((req_msg->seg_buf_len + fd->file_size) > fd->buf_size)) {
|
||||
cnss_plat_ipc_err("Segment buf ID: %d buffer size %d not allowed\n",
|
||||
req_msg->seg_index, req_msg->seg_buf_len);
|
||||
goto file_error;
|
||||
}
|
||||
if (req_msg->seg_index != fd->seg_index) {
|
||||
cnss_plat_ipc_err("File %s transfer segment failure\n",
|
||||
fd->name);
|
||||
goto file_error;
|
||||
}
|
||||
|
||||
memcpy(fd->buf, req_msg->seg_buf, req_msg->seg_buf_len);
|
||||
fd->seg_index++;
|
||||
fd->buf += req_msg->seg_buf_len;
|
||||
fd->file_size += req_msg->seg_buf_len;
|
||||
|
||||
resp.file_id = fd->id;
|
||||
resp.seg_index = fd->seg_index;
|
||||
ret = qmi_send_response
|
||||
(svc->svc_hdl, sq, txn,
|
||||
CNSS_PLAT_IPC_QMI_FILE_DOWNLOAD_RESP_V01,
|
||||
CNSS_PLAT_IPC_QMI_FILE_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN,
|
||||
cnss_plat_ipc_qmi_file_download_resp_msg_v01_ei,
|
||||
&resp);
|
||||
|
||||
if (ret < 0)
|
||||
cnss_plat_ipc_err("QMI failed: %d\n", ret);
|
||||
|
||||
if (req_msg->end) {
|
||||
fd->end = true;
|
||||
complete(&fd->complete);
|
||||
}
|
||||
|
||||
return;
|
||||
file_error:
|
||||
complete(&fd->complete);
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_qmi_init_setup_req_handler() - Init_Setup QMI message handler
|
||||
* @handle: Pointer to QMI handle
|
||||
* @sq: QMI socket
|
||||
* @txn: QMI transaction pointer
|
||||
* @decoded_msg: Pointer to decoded QMI message
|
||||
*
|
||||
* Handles the QMI Init setup handshake message from userspace.
|
||||
* buffer.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void
|
||||
cnss_plat_ipc_qmi_init_setup_req_handler(struct qmi_handle *handle,
|
||||
struct sockaddr_qrtr *sq,
|
||||
struct qmi_txn *txn,
|
||||
const void *decoded_msg)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_init_setup_req_msg_v01 *req_msg;
|
||||
struct cnss_plat_ipc_qmi_init_setup_resp_msg_v01 resp = {0};
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
struct cnss_plat_ipc_daemon_config *cfg = &daemon_cfg;
|
||||
int ret = 0;
|
||||
|
||||
req_msg =
|
||||
(struct cnss_plat_ipc_qmi_init_setup_req_msg_v01 *)decoded_msg;
|
||||
cnss_plat_ipc_dbg("MAC: %d HW_TRC: %d CAL: %d\n",
|
||||
req_msg->dms_mac_addr_supported,
|
||||
req_msg->qdss_hw_trace_override,
|
||||
req_msg->cal_file_available_bitmask);
|
||||
|
||||
cfg->dms_mac_addr_supported = req_msg->dms_mac_addr_supported;
|
||||
cfg->qdss_hw_trace_override = req_msg->qdss_hw_trace_override;
|
||||
cfg->cal_file_available_bitmask = req_msg->cal_file_available_bitmask;
|
||||
cfg->initialized = 1;
|
||||
|
||||
ret = qmi_send_response
|
||||
(svc->svc_hdl, sq, txn,
|
||||
CNSS_PLAT_IPC_QMI_INIT_SETUP_RESP_V01,
|
||||
CNSS_PLAT_IPC_QMI_INIT_SETUP_RESP_MSG_V01_MAX_MSG_LEN,
|
||||
cnss_plat_ipc_qmi_init_setup_resp_msg_v01_ei, &resp);
|
||||
if (ret < 0)
|
||||
cnss_plat_ipc_err("%s: QMI failed: %d\n", __func__, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_qmi_reg_client_req_handler() - Register QMI client
|
||||
* @handle: Pointer to QMI handle
|
||||
* @sq: QMI socket
|
||||
* @txn: QMI transaction pointer
|
||||
* @decoded_msg: Pointer to decoded QMI message
|
||||
*
|
||||
* Handles the userspace QMI client registration.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void
|
||||
cnss_plat_ipc_qmi_reg_client_req_handler(struct qmi_handle *handle,
|
||||
struct sockaddr_qrtr *sq,
|
||||
struct qmi_txn *txn,
|
||||
const void *decoded_msg)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_reg_client_req_msg_v01 *req_msg;
|
||||
struct cnss_plat_ipc_qmi_reg_client_resp_msg_v01 resp = {0};
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
struct cnss_plat_ipc_qmi_client_ctx *qmi_client = svc->qmi_client_ctx;
|
||||
int ret = 0;
|
||||
|
||||
req_msg =
|
||||
(struct cnss_plat_ipc_qmi_reg_client_req_msg_v01 *)decoded_msg;
|
||||
|
||||
if (req_msg->client_id_valid) {
|
||||
if (req_msg->client_id <= CNSS_PLAT_IPC_MAX_QMI_CLIENTS &&
|
||||
!qmi_client[req_msg->client_id].client_connected) {
|
||||
cnss_plat_ipc_info
|
||||
("%s: QMI Client Connected. QMI Socket Node: %d Port: %d ID: %d\n",
|
||||
__func__, sq->sq_node, sq->sq_port,
|
||||
req_msg->client_id);
|
||||
qmi_client[req_msg->client_id].client_sq = *sq;
|
||||
qmi_client[req_msg->client_id].client_connected = true;
|
||||
cnss_plat_ipc_qmi_update_user
|
||||
((enum cnss_plat_ipc_qmi_client_id_v01)
|
||||
req_msg->client_id);
|
||||
} else {
|
||||
cnss_plat_ipc_err("QMI client already connected or Invalid client id\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ret = qmi_send_response
|
||||
(svc->svc_hdl, sq, txn,
|
||||
CNSS_PLAT_IPC_QMI_REG_CLIENT_RESP_V01,
|
||||
CNSS_PLAT_IPC_QMI_REG_CLIENT_RESP_MSG_V01_MAX_MSG_LEN,
|
||||
cnss_plat_ipc_qmi_reg_client_resp_msg_v01_ei, &resp);
|
||||
|
||||
if (ret < 0)
|
||||
cnss_plat_ipc_err("QMI failed: %d\n", ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_qmi_disconnect_cb() - Handler for QMI node disconnect specific
|
||||
* to node and port
|
||||
* @handle: Pointer to QMI handle
|
||||
* @node: QMI node that is disconnected
|
||||
* @port: QMI port that is disconnected
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void cnss_plat_ipc_qmi_disconnect_cb(struct qmi_handle *handle,
|
||||
unsigned int node,
|
||||
unsigned int port)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
struct cnss_plat_ipc_qmi_client_ctx *qmi_client =
|
||||
svc->qmi_client_ctx;
|
||||
struct cnss_plat_ipc_file_data *fd;
|
||||
u32 file_id;
|
||||
int i;
|
||||
|
||||
if (svc->svc_hdl != handle) {
|
||||
cnss_plat_ipc_err("Invalid QMI Handle\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i <= CNSS_PLAT_IPC_MAX_QMI_CLIENTS; i++) {
|
||||
if (qmi_client[i].client_connected &&
|
||||
qmi_client[i].client_sq.sq_node == node &&
|
||||
qmi_client[i].client_sq.sq_port == port) {
|
||||
cnss_plat_ipc_err
|
||||
("%s: QMI client disconnect. QMI Socket Node:%d Port:%d ID: %d\n",
|
||||
__func__, node, port, i);
|
||||
qmi_client[i].client_sq.sq_node = 0;
|
||||
qmi_client[i].client_sq.sq_port = 0;
|
||||
qmi_client[i].client_sq.sq_family = 0;
|
||||
qmi_client[i].client_connected = false;
|
||||
|
||||
/* Daemon killed. Fail any download / upload in progress. This
|
||||
* will also free stale fd
|
||||
*/
|
||||
mutex_lock(&svc->file_idr_lock);
|
||||
idr_for_each_entry(&svc->file_idr, fd, file_id)
|
||||
complete(&fd->complete);
|
||||
mutex_unlock(&svc->file_idr_lock);
|
||||
cnss_plat_ipc_qmi_update_user(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_qmi_bye_cb() - Handler for QMI node disconnect for all port of
|
||||
* the given node.
|
||||
* @handle: Pointer to QMI handle
|
||||
* @node: QMI node that is disconnected
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void cnss_plat_ipc_qmi_bye_cb(struct qmi_handle *handle,
|
||||
unsigned int node)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
struct cnss_plat_ipc_qmi_client_ctx *qmi_client =
|
||||
svc->qmi_client_ctx;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= CNSS_PLAT_IPC_MAX_QMI_CLIENTS; i++) {
|
||||
cnss_plat_ipc_qmi_disconnect_cb
|
||||
(handle, node,
|
||||
qmi_client[i].client_sq.sq_port);
|
||||
}
|
||||
}
|
||||
|
||||
static struct qmi_ops cnss_plat_ipc_qmi_ops = {
|
||||
/* inform a client that all clients from a node are gone */
|
||||
.bye = cnss_plat_ipc_qmi_bye_cb,
|
||||
.del_client = cnss_plat_ipc_qmi_disconnect_cb,
|
||||
};
|
||||
|
||||
static struct qmi_msg_handler cnss_plat_ipc_qmi_req_handlers[] = {
|
||||
{
|
||||
.type = QMI_REQUEST,
|
||||
.msg_id = CNSS_PLAT_IPC_QMI_REG_CLIENT_REQ_V01,
|
||||
.ei = cnss_plat_ipc_qmi_reg_client_req_msg_v01_ei,
|
||||
.decoded_size =
|
||||
sizeof(struct cnss_plat_ipc_qmi_reg_client_req_msg_v01),
|
||||
.fn = cnss_plat_ipc_qmi_reg_client_req_handler,
|
||||
},
|
||||
{
|
||||
.type = QMI_REQUEST,
|
||||
.msg_id = CNSS_PLAT_IPC_QMI_INIT_SETUP_REQ_V01,
|
||||
.ei = cnss_plat_ipc_qmi_init_setup_req_msg_v01_ei,
|
||||
.decoded_size =
|
||||
sizeof(struct cnss_plat_ipc_qmi_init_setup_req_msg_v01),
|
||||
.fn = cnss_plat_ipc_qmi_init_setup_req_handler,
|
||||
},
|
||||
{
|
||||
.type = QMI_REQUEST,
|
||||
.msg_id = CNSS_PLAT_IPC_QMI_FILE_DOWNLOAD_REQ_V01,
|
||||
.ei = cnss_plat_ipc_qmi_file_download_req_msg_v01_ei,
|
||||
.decoded_size =
|
||||
sizeof(struct cnss_plat_ipc_qmi_file_download_req_msg_v01),
|
||||
.fn = cnss_plat_ipc_qmi_file_download_req_handler,
|
||||
},
|
||||
{
|
||||
.type = QMI_REQUEST,
|
||||
.msg_id = CNSS_PLAT_IPC_QMI_FILE_UPLOAD_REQ_V01,
|
||||
.ei = cnss_plat_ipc_qmi_file_upload_req_msg_v01_ei,
|
||||
.decoded_size =
|
||||
sizeof(struct cnss_plat_ipc_qmi_file_upload_req_msg_v01),
|
||||
.fn = cnss_plat_ipc_qmi_file_upload_req_handler,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_qmi_daemon_config() - Get daemon config for CNSS platform
|
||||
*
|
||||
* Return: Pointer to daemon client config
|
||||
*/
|
||||
struct cnss_plat_ipc_daemon_config *cnss_plat_ipc_qmi_daemon_config(void)
|
||||
{
|
||||
int i;
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
struct cnss_plat_ipc_qmi_client_ctx *qmi_client =
|
||||
&svc->qmi_client_ctx[CNSS_PLAT_IPC_DAEMON_QMI_CLIENT_V01];
|
||||
|
||||
if (!qmi_client->client_connected)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < CNSS_DAEMON_CFG_WAIT_RETRY; i++) {
|
||||
if (daemon_cfg.initialized == 1)
|
||||
break;
|
||||
|
||||
msleep(CNSS_DAEMON_CFG_WAIT_MS);
|
||||
}
|
||||
|
||||
return &daemon_cfg;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_qmi_daemon_config);
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_register() - Register for QMI IPC client status update
|
||||
* @client_id: User space QMI IPC client ID. Also works as
|
||||
* array index for QMI client context
|
||||
* @connect_update_cb: Function pointer for callback
|
||||
* @cb_ctx: Callback context
|
||||
*
|
||||
* Return: 0 on success, negative error value otherwise
|
||||
*/
|
||||
int cnss_plat_ipc_register(enum cnss_plat_ipc_qmi_client_id_v01 client_id,
|
||||
cnss_plat_ipc_connection_update
|
||||
connection_update_cb, void *cb_ctx)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
struct cnss_plat_ipc_qmi_client_ctx *qmi_client;
|
||||
int num_user;
|
||||
|
||||
if (client_id > CNSS_PLAT_IPC_MAX_QMI_CLIENTS) {
|
||||
cnss_plat_ipc_err("Invalid Client ID: %d\n", client_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qmi_client = &svc->qmi_client_ctx[client_id];
|
||||
num_user = qmi_client->num_user;
|
||||
|
||||
if (num_user >= CNSS_PLAT_IPC_MAX_USER) {
|
||||
cnss_plat_ipc_err("Max Service users reached\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qmi_client->connection_update_cb[num_user] = connection_update_cb;
|
||||
qmi_client->cb_ctx[num_user] = cb_ctx;
|
||||
qmi_client->num_user++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_register);
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_unregister() - Unregister QMI IPC client status callback
|
||||
* @client_id: User space QMI IPC client ID. Also works as
|
||||
* array index for QMI client context
|
||||
* @cb_cbt: Callback context provided during registration
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void cnss_plat_ipc_unregister(enum cnss_plat_ipc_qmi_client_id_v01 client_id,
|
||||
void *cb_ctx)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
struct cnss_plat_ipc_qmi_client_ctx *qmi_client;
|
||||
int i;
|
||||
|
||||
if (client_id > CNSS_PLAT_IPC_MAX_QMI_CLIENTS) {
|
||||
cnss_plat_ipc_err("Invalid Client ID: %d\n", client_id);
|
||||
return;
|
||||
}
|
||||
|
||||
qmi_client = &svc->qmi_client_ctx[client_id];
|
||||
|
||||
for (i = 0; i < qmi_client->num_user; i++) {
|
||||
if (qmi_client->cb_ctx[i] == cb_ctx) {
|
||||
qmi_client->cb_ctx[i] = NULL;
|
||||
qmi_client->connection_update_cb[i] = NULL;
|
||||
qmi_client->num_user--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_unregister);
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_init_fn() - CNSS Platform qmi service init function
|
||||
*
|
||||
* Initialize a QMI client handle and register new QMI service for CNSS Platform
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void cnss_plat_ipc_init_fn(struct work_struct *work)
|
||||
{
|
||||
int ret = 0, retry = 0;
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
|
||||
svc->svc_hdl = kzalloc(sizeof(*svc->svc_hdl), GFP_KERNEL);
|
||||
if (!svc->svc_hdl)
|
||||
return;
|
||||
|
||||
retry:
|
||||
ret = qmi_handle_init(svc->svc_hdl,
|
||||
CNSS_PLAT_IPC_QMI_MAX_MSG_SIZE_V01,
|
||||
&cnss_plat_ipc_qmi_ops,
|
||||
cnss_plat_ipc_qmi_req_handlers);
|
||||
if (ret < 0) {
|
||||
/* If QMI fails to init, retry for total
|
||||
* QMI_INIT_RETRY_DELAY_MS * QMI_INIT_RETRY_MAX_TIMES ms.
|
||||
*/
|
||||
if (retry++ < QMI_INIT_RETRY_MAX_TIMES) {
|
||||
msleep(QMI_INIT_RETRY_DELAY_MS);
|
||||
goto retry;
|
||||
}
|
||||
cnss_plat_ipc_err("Failed to init QMI handle after %d ms * %d, err = %d\n",
|
||||
QMI_INIT_RETRY_DELAY_MS,
|
||||
QMI_INIT_RETRY_MAX_TIMES, ret);
|
||||
goto free_svc_hdl;
|
||||
}
|
||||
|
||||
ret = qmi_add_server(svc->svc_hdl,
|
||||
CNSS_PLATFORM_SERVICE_ID_V01,
|
||||
CNSS_PLATFORM_SERVICE_VERS_V01, 0);
|
||||
if (ret < 0) {
|
||||
cnss_plat_ipc_err("Server add fail: %d\n", ret);
|
||||
goto release_svc_hdl;
|
||||
}
|
||||
|
||||
cnss_plat_ipc_info("CNSS Platform IPC QMI Service is started\n");
|
||||
idr_init(&svc->file_idr);
|
||||
mutex_init(&svc->file_idr_lock);
|
||||
return;
|
||||
|
||||
release_svc_hdl:
|
||||
qmi_handle_release(svc->svc_hdl);
|
||||
free_svc_hdl:
|
||||
kfree(svc->svc_hdl);
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_is_valid_dt_node_found - Check if valid device tree node
|
||||
* present
|
||||
*
|
||||
* Valid device tree node means a node with "qcom,wlan" property present
|
||||
* and "status" property not disabled.
|
||||
*
|
||||
* Return: true if valid device tree node found, false if not found
|
||||
*/
|
||||
static bool cnss_plat_ipc_is_valid_dt_node_found(void)
|
||||
{
|
||||
struct device_node *dn = NULL;
|
||||
|
||||
for_each_node_with_property(dn, "qcom,wlan") {
|
||||
if (of_device_is_available(dn))
|
||||
break;
|
||||
}
|
||||
|
||||
if (dn)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static DECLARE_WORK(cnss_plat_ipc_init_work, cnss_plat_ipc_init_fn);
|
||||
|
||||
static int __init cnss_plat_ipc_qmi_svc_init(void)
|
||||
{
|
||||
if (!cnss_plat_ipc_is_valid_dt_node_found())
|
||||
return -ENODEV;
|
||||
|
||||
/* Schedule a work to do real init to avoid blocking here */
|
||||
cnss_plat_ipc_logging_init();
|
||||
schedule_work(&cnss_plat_ipc_init_work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_qmi_svc_exit() - CNSS Platform qmi service exit
|
||||
*
|
||||
* Release all resources during exit
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void __exit cnss_plat_ipc_qmi_svc_exit(void)
|
||||
{
|
||||
struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
|
||||
|
||||
cancel_work_sync(&cnss_plat_ipc_init_work);
|
||||
|
||||
if (svc->svc_hdl) {
|
||||
qmi_handle_release(svc->svc_hdl);
|
||||
kfree(svc->svc_hdl);
|
||||
idr_destroy(&svc->file_idr);
|
||||
}
|
||||
|
||||
cnss_plat_ipc_logging_deinit();
|
||||
}
|
||||
|
||||
module_init(cnss_plat_ipc_qmi_svc_init);
|
||||
module_exit(cnss_plat_ipc_qmi_svc_exit);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("CNSS Platform IPC QMI Service");
|
@@ -0,0 +1,90 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CNSS_PLAT_IPC_QMI_H
|
||||
#define _CNSS_PLAT_IPC_QMI_H
|
||||
|
||||
#include "cnss_plat_ipc_service_v01.h"
|
||||
|
||||
/* As the value of CNSS_PLAT_IPC_MAX_QMI_CLIENTS will keep changing
|
||||
* addition of new QMI client, it cannot be kept in IDL as change in
|
||||
* existing value can cause backward compatibily issue. Keep it here
|
||||
* and update its value with new QMI client ID added in enum in IDL.
|
||||
*/
|
||||
#define CNSS_PLAT_IPC_MAX_QMI_CLIENTS CNSS_PLAT_IPC_DAEMON_QMI_CLIENT_V01
|
||||
|
||||
/**
|
||||
* cnss_plat_ipc_daemon_config: Config options provided by cnss-daemon
|
||||
* @initialized: Set when daemon configs are initialized
|
||||
* @dms_mac_addr_supported: DMS MAC address provisioning support
|
||||
* @qdss_hw_trace_override: QDSS config for HW trace enable
|
||||
* @cal_file_available_bitmask: Calibration file available
|
||||
*/
|
||||
struct cnss_plat_ipc_daemon_config {
|
||||
u8 initialized;
|
||||
u8 dms_mac_addr_supported;
|
||||
u8 qdss_hw_trace_override;
|
||||
u32 cal_file_available_bitmask;
|
||||
};
|
||||
|
||||
typedef void (*cnss_plat_ipc_connection_update)(void *cb_ctx,
|
||||
bool connection_status);
|
||||
|
||||
/**
|
||||
* Persistent caldb file store which is a runtime FW param based feature will
|
||||
* fail if CONFIG_CNSS_PLAT_IPC_QMI_SVC is not enabled.
|
||||
**/
|
||||
#if IS_ENABLED(CONFIG_CNSS_PLAT_IPC_QMI_SVC)
|
||||
int cnss_plat_ipc_register(enum cnss_plat_ipc_qmi_client_id_v01 client_id,
|
||||
cnss_plat_ipc_connection_update
|
||||
connection_update_cb, void *cb_ctx);
|
||||
void cnss_plat_ipc_unregister(enum cnss_plat_ipc_qmi_client_id_v01 client_id,
|
||||
void *cb_ctx);
|
||||
int cnss_plat_ipc_qmi_file_download(enum cnss_plat_ipc_qmi_client_id_v01
|
||||
client_id, char *file_name, char *buf,
|
||||
u32 *size);
|
||||
int cnss_plat_ipc_qmi_file_upload(enum cnss_plat_ipc_qmi_client_id_v01
|
||||
client_id, char *file_name, u8 *file_buf,
|
||||
u32 file_size);
|
||||
struct cnss_plat_ipc_daemon_config *cnss_plat_ipc_qmi_daemon_config(void);
|
||||
#else
|
||||
static inline
|
||||
int cnss_plat_ipc_register(enum cnss_plat_ipc_qmi_client_id_v01 client_id,
|
||||
cnss_plat_ipc_connection_update
|
||||
connection_update_cb, void *cb_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
void cnss_plat_ipc_unregister(enum cnss_plat_ipc_qmi_client_id_v01 client_id,
|
||||
void *cb_ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_plat_ipc_qmi_file_download(enum cnss_plat_ipc_qmi_client_id_v01
|
||||
client_id, char *file_name, char *buf,
|
||||
u32 *size)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_plat_ipc_qmi_file_upload(enum cnss_plat_ipc_qmi_client_id_v01
|
||||
client_id, char *file_name, u8 *file_buf,
|
||||
u32 file_size)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct cnss_plat_ipc_daemon_config *cnss_plat_ipc_qmi_daemon_config(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
@@ -0,0 +1,402 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#include "cnss_plat_ipc_service_v01.h"
|
||||
#include <linux/module.h>
|
||||
|
||||
struct qmi_elem_info cnss_plat_ipc_qmi_init_setup_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_init_setup_req_msg_v01,
|
||||
dms_mac_addr_supported),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_init_setup_req_msg_v01,
|
||||
qdss_hw_trace_override),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x03,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_init_setup_req_msg_v01,
|
||||
cal_file_available_bitmask),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_qmi_init_setup_req_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info cnss_plat_ipc_qmi_init_setup_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_init_setup_resp_msg_v01,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u64),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x03,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_init_setup_resp_msg_v01,
|
||||
drv_status),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_qmi_init_setup_resp_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info cnss_plat_ipc_qmi_file_download_ind_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRING,
|
||||
.elem_len = CNSS_PLAT_IPC_QMI_MAX_FILE_NAME_LEN_V01 + 1,
|
||||
.elem_size = sizeof(char),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_download_ind_msg_v01,
|
||||
file_name),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_download_ind_msg_v01,
|
||||
file_id),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_qmi_file_download_ind_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info cnss_plat_ipc_qmi_file_download_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_download_req_msg_v01,
|
||||
file_id),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_download_req_msg_v01,
|
||||
file_size),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x03,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_download_req_msg_v01,
|
||||
end),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x04,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_download_req_msg_v01,
|
||||
seg_index),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_DATA_LEN,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u16),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x05,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_download_req_msg_v01,
|
||||
seg_buf_len),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = CNSS_PLAT_IPC_QMI_MAX_DATA_SIZE_V01,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = VAR_LEN_ARRAY,
|
||||
.tlv_type = 0x05,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_download_req_msg_v01,
|
||||
seg_buf),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_qmi_file_download_req_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info cnss_plat_ipc_qmi_file_download_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_download_resp_msg_v01,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x03,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_download_resp_msg_v01,
|
||||
file_id),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x04,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_download_resp_msg_v01,
|
||||
seg_index),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_qmi_file_download_resp_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info cnss_plat_ipc_qmi_file_upload_ind_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRING,
|
||||
.elem_len = CNSS_PLAT_IPC_QMI_MAX_FILE_NAME_LEN_V01 + 1,
|
||||
.elem_size = sizeof(char),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_upload_ind_msg_v01,
|
||||
file_name),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_upload_ind_msg_v01,
|
||||
file_id),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x03,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_upload_ind_msg_v01,
|
||||
file_size),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_qmi_file_upload_ind_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info cnss_plat_ipc_qmi_file_upload_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_upload_req_msg_v01,
|
||||
file_id),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_upload_req_msg_v01,
|
||||
seg_index),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_qmi_file_upload_req_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info cnss_plat_ipc_qmi_file_upload_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_upload_resp_msg_v01,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x03,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_upload_resp_msg_v01,
|
||||
file_id),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x04,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_upload_resp_msg_v01,
|
||||
end),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x05,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_upload_resp_msg_v01,
|
||||
seg_index),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_DATA_LEN,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u16),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x06,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_upload_resp_msg_v01,
|
||||
seg_buf_len),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = CNSS_PLAT_IPC_QMI_MAX_DATA_SIZE_V01,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = VAR_LEN_ARRAY,
|
||||
.tlv_type = 0x06,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_file_upload_resp_msg_v01,
|
||||
seg_buf),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_qmi_file_upload_resp_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info cnss_plat_ipc_qmi_reg_client_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_reg_client_req_msg_v01,
|
||||
client_id_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_SIGNED_4_BYTE_ENUM,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(enum cnss_plat_ipc_qmi_client_id_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_reg_client_req_msg_v01,
|
||||
client_id),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_qmi_reg_client_req_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info cnss_plat_ipc_qmi_reg_client_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct
|
||||
cnss_plat_ipc_qmi_reg_client_resp_msg_v01,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(cnss_plat_ipc_qmi_reg_client_resp_msg_v01_ei);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("WLAN FW QMI service");
|
@@ -0,0 +1,127 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef CNSS_PLAT_IPC_SERVICE_V01_H
|
||||
#define CNSS_PLAT_IPC_SERVICE_V01_H
|
||||
|
||||
#include <linux/soc/qcom/qmi.h>
|
||||
|
||||
#define CNSS_PLATFORM_SERVICE_ID_V01 0x42E
|
||||
#define CNSS_PLATFORM_SERVICE_VERS_V01 0x01
|
||||
|
||||
#define CNSS_PLAT_IPC_QMI_REG_CLIENT_RESP_V01 0x0006
|
||||
#define CNSS_PLAT_IPC_QMI_FILE_DOWNLOAD_REQ_V01 0x0003
|
||||
#define CNSS_PLAT_IPC_QMI_FILE_UPLOAD_IND_V01 0x0004
|
||||
#define CNSS_PLAT_IPC_QMI_FILE_DOWNLOAD_IND_V01 0x0002
|
||||
#define CNSS_PLAT_IPC_QMI_REG_CLIENT_REQ_V01 0x0006
|
||||
#define CNSS_PLAT_IPC_QMI_INIT_SETUP_REQ_V01 0x0001
|
||||
#define CNSS_PLAT_IPC_QMI_FILE_UPLOAD_REQ_V01 0x0005
|
||||
#define CNSS_PLAT_IPC_QMI_FILE_DOWNLOAD_RESP_V01 0x0003
|
||||
#define CNSS_PLAT_IPC_QMI_FILE_UPLOAD_RESP_V01 0x0005
|
||||
#define CNSS_PLAT_IPC_QMI_INIT_SETUP_RESP_V01 0x0001
|
||||
|
||||
#define CNSS_PLAT_IPC_QMI_MAX_FILE_NAME_LEN_V01 32
|
||||
#define CNSS_PLAT_IPC_QMI_MAX_DATA_SIZE_V01 61440
|
||||
#define CNSS_PLAT_IPC_QMI_MAX_MSG_SIZE_V01 65535
|
||||
|
||||
#define CNSS_PLAT_IPC_QMI_DRIVER_CBC_DONE_V01 ((u64)0x01ULL)
|
||||
#define CNSS_PLAT_IPC_QMI_DRIVER_WLAN_ACTIVE_V01 ((u64)0x02ULL)
|
||||
|
||||
enum cnss_plat_ipc_qmi_client_id_v01 {
|
||||
CNSS_PLAT_IPC_QMI_CLIENT_ID_MIN_VAL_V01 = INT_MIN,
|
||||
CNSS_PLAT_IPC_BT_QMI_CLIENT_V01 = 0,
|
||||
CNSS_PLAT_IPC_DAEMON_QMI_CLIENT_V01 = 1,
|
||||
CNSS_PLAT_IPC_QMI_CLIENT_ID_MAX_VAL_V01 = INT_MAX,
|
||||
};
|
||||
|
||||
struct cnss_plat_ipc_qmi_init_setup_req_msg_v01 {
|
||||
u8 dms_mac_addr_supported;
|
||||
u8 qdss_hw_trace_override;
|
||||
u32 cal_file_available_bitmask;
|
||||
};
|
||||
|
||||
#define CNSS_PLAT_IPC_QMI_INIT_SETUP_REQ_MSG_V01_MAX_MSG_LEN 15
|
||||
extern struct qmi_elem_info cnss_plat_ipc_qmi_init_setup_req_msg_v01_ei[];
|
||||
|
||||
struct cnss_plat_ipc_qmi_init_setup_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
u64 drv_status;
|
||||
};
|
||||
|
||||
#define CNSS_PLAT_IPC_QMI_INIT_SETUP_RESP_MSG_V01_MAX_MSG_LEN 18
|
||||
extern struct qmi_elem_info cnss_plat_ipc_qmi_init_setup_resp_msg_v01_ei[];
|
||||
|
||||
struct cnss_plat_ipc_qmi_file_download_ind_msg_v01 {
|
||||
char file_name[CNSS_PLAT_IPC_QMI_MAX_FILE_NAME_LEN_V01 + 1];
|
||||
u32 file_id;
|
||||
};
|
||||
|
||||
#define CNSS_PLAT_IPC_QMI_FILE_DOWNLOAD_IND_MSG_V01_MAX_MSG_LEN 42
|
||||
extern struct qmi_elem_info cnss_plat_ipc_qmi_file_download_ind_msg_v01_ei[];
|
||||
|
||||
struct cnss_plat_ipc_qmi_file_download_req_msg_v01 {
|
||||
u32 file_id;
|
||||
u32 file_size;
|
||||
u8 end;
|
||||
u32 seg_index;
|
||||
u32 seg_buf_len;
|
||||
u8 seg_buf[CNSS_PLAT_IPC_QMI_MAX_DATA_SIZE_V01];
|
||||
};
|
||||
|
||||
#define CNSS_PLAT_IPC_QMI_FILE_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 61470
|
||||
extern struct qmi_elem_info cnss_plat_ipc_qmi_file_download_req_msg_v01_ei[];
|
||||
|
||||
struct cnss_plat_ipc_qmi_file_download_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
u32 file_id;
|
||||
u32 seg_index;
|
||||
};
|
||||
|
||||
#define CNSS_PLAT_IPC_QMI_FILE_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 21
|
||||
extern struct qmi_elem_info cnss_plat_ipc_qmi_file_download_resp_msg_v01_ei[];
|
||||
|
||||
struct cnss_plat_ipc_qmi_file_upload_ind_msg_v01 {
|
||||
char file_name[CNSS_PLAT_IPC_QMI_MAX_FILE_NAME_LEN_V01 + 1];
|
||||
u32 file_id;
|
||||
u32 file_size;
|
||||
};
|
||||
|
||||
#define CNSS_PLAT_IPC_QMI_FILE_UPLOAD_IND_MSG_V01_MAX_MSG_LEN 49
|
||||
extern struct qmi_elem_info cnss_plat_ipc_qmi_file_upload_ind_msg_v01_ei[];
|
||||
|
||||
struct cnss_plat_ipc_qmi_file_upload_req_msg_v01 {
|
||||
u32 file_id;
|
||||
u32 seg_index;
|
||||
};
|
||||
|
||||
#define CNSS_PLAT_IPC_QMI_FILE_UPLOAD_REQ_MSG_V01_MAX_MSG_LEN 14
|
||||
extern struct qmi_elem_info cnss_plat_ipc_qmi_file_upload_req_msg_v01_ei[];
|
||||
|
||||
struct cnss_plat_ipc_qmi_file_upload_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
u32 file_id;
|
||||
u8 end;
|
||||
u32 seg_index;
|
||||
u32 seg_buf_len;
|
||||
u8 seg_buf[CNSS_PLAT_IPC_QMI_MAX_DATA_SIZE_V01];
|
||||
};
|
||||
|
||||
#define CNSS_PLAT_IPC_QMI_FILE_UPLOAD_RESP_MSG_V01_MAX_MSG_LEN 61470
|
||||
extern struct qmi_elem_info cnss_plat_ipc_qmi_file_upload_resp_msg_v01_ei[];
|
||||
|
||||
struct cnss_plat_ipc_qmi_reg_client_req_msg_v01 {
|
||||
u8 client_id_valid;
|
||||
enum cnss_plat_ipc_qmi_client_id_v01 client_id;
|
||||
};
|
||||
|
||||
#define CNSS_PLAT_IPC_QMI_REG_CLIENT_REQ_MSG_V01_MAX_MSG_LEN 7
|
||||
extern struct qmi_elem_info cnss_plat_ipc_qmi_reg_client_req_msg_v01_ei[];
|
||||
|
||||
struct cnss_plat_ipc_qmi_reg_client_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
|
||||
#define CNSS_PLAT_IPC_QMI_REG_CLIENT_RESP_MSG_V01_MAX_MSG_LEN 7
|
||||
extern struct qmi_elem_info cnss_plat_ipc_qmi_reg_client_resp_msg_v01_ei[];
|
||||
|
||||
#endif
|
@@ -0,0 +1,590 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017, 2019, 2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "cnss_utils: " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/of.h>
|
||||
#ifdef CONFIG_CNSS_OUT_OF_TREE
|
||||
#include "cnss_utils.h"
|
||||
#else
|
||||
#include <net/cnss_utils.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FEATURE_SMEM_MAILBOX
|
||||
#include <smem-mailbox.h>
|
||||
#endif
|
||||
|
||||
#define CNSS_MAX_CH_NUM 157
|
||||
struct cnss_unsafe_channel_list {
|
||||
u16 unsafe_ch_count;
|
||||
u16 unsafe_ch_list[CNSS_MAX_CH_NUM];
|
||||
};
|
||||
|
||||
struct cnss_dfs_nol_info {
|
||||
void *dfs_nol_info;
|
||||
u16 dfs_nol_info_len;
|
||||
};
|
||||
|
||||
#define MAX_NO_OF_MAC_ADDR 4
|
||||
#define MAC_PREFIX_LEN 2
|
||||
struct cnss_wlan_mac_addr {
|
||||
u8 mac_addr[MAX_NO_OF_MAC_ADDR][ETH_ALEN];
|
||||
u32 no_of_mac_addr_set;
|
||||
};
|
||||
|
||||
enum mac_type {
|
||||
CNSS_MAC_PROVISIONED,
|
||||
CNSS_MAC_DERIVED,
|
||||
};
|
||||
|
||||
static struct cnss_utils_priv {
|
||||
struct cnss_unsafe_channel_list unsafe_channel_list;
|
||||
struct cnss_dfs_nol_info dfs_nol_info;
|
||||
/* generic mutex for unsafe channel */
|
||||
struct mutex unsafe_channel_list_lock;
|
||||
/* generic spin-lock for dfs_nol info */
|
||||
spinlock_t dfs_nol_info_lock;
|
||||
int driver_load_cnt;
|
||||
struct cnss_wlan_mac_addr wlan_mac_addr;
|
||||
struct cnss_wlan_mac_addr wlan_der_mac_addr;
|
||||
enum cnss_utils_cc_src cc_source;
|
||||
struct dentry *root_dentry;
|
||||
/* generic mutex for device_id */
|
||||
struct mutex cnss_device_id_lock;
|
||||
enum cnss_utils_device_type cnss_device_type;
|
||||
#ifdef CONFIG_FEATURE_SMEM_MAILBOX
|
||||
bool smem_mailbox_initialized;
|
||||
int smem_mailbox_id;
|
||||
#endif
|
||||
} *cnss_utils_priv;
|
||||
|
||||
int cnss_utils_set_wlan_unsafe_channel(struct device *dev,
|
||||
u16 *unsafe_ch_list, u16 ch_count)
|
||||
{
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
|
||||
if (!priv)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&priv->unsafe_channel_list_lock);
|
||||
if (!unsafe_ch_list || ch_count > CNSS_MAX_CH_NUM) {
|
||||
mutex_unlock(&priv->unsafe_channel_list_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->unsafe_channel_list.unsafe_ch_count = ch_count;
|
||||
|
||||
if (ch_count == 0)
|
||||
goto end;
|
||||
|
||||
memcpy(priv->unsafe_channel_list.unsafe_ch_list,
|
||||
unsafe_ch_list, ch_count * sizeof(u16));
|
||||
|
||||
end:
|
||||
mutex_unlock(&priv->unsafe_channel_list_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_set_wlan_unsafe_channel);
|
||||
|
||||
int cnss_utils_get_wlan_unsafe_channel(struct device *dev,
|
||||
u16 *unsafe_ch_list,
|
||||
u16 *ch_count, u16 buf_len)
|
||||
{
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
|
||||
if (!priv)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&priv->unsafe_channel_list_lock);
|
||||
if (!unsafe_ch_list || !ch_count) {
|
||||
mutex_unlock(&priv->unsafe_channel_list_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (buf_len <
|
||||
(priv->unsafe_channel_list.unsafe_ch_count * sizeof(u16))) {
|
||||
mutex_unlock(&priv->unsafe_channel_list_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*ch_count = priv->unsafe_channel_list.unsafe_ch_count;
|
||||
memcpy(unsafe_ch_list, priv->unsafe_channel_list.unsafe_ch_list,
|
||||
priv->unsafe_channel_list.unsafe_ch_count * sizeof(u16));
|
||||
mutex_unlock(&priv->unsafe_channel_list_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_get_wlan_unsafe_channel);
|
||||
|
||||
enum cnss_utils_device_type cnss_utils_update_device_type(
|
||||
enum cnss_utils_device_type device_type)
|
||||
{
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
|
||||
if (!priv)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&priv->cnss_device_id_lock);
|
||||
pr_info("cnss_utils: device type:%d\n", device_type);
|
||||
if (priv->cnss_device_type == CNSS_UNSUPPORETD_DEVICE_TYPE) {
|
||||
priv->cnss_device_type = device_type;
|
||||
pr_info("cnss_utils: set device type:%d\n",
|
||||
priv->cnss_device_type);
|
||||
} else {
|
||||
pr_info("cnss_utils: device type already set :%d\n",
|
||||
priv->cnss_device_type);
|
||||
}
|
||||
mutex_unlock(&priv->cnss_device_id_lock);
|
||||
return priv->cnss_device_type;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_update_device_type);
|
||||
|
||||
int cnss_utils_wlan_set_dfs_nol(struct device *dev,
|
||||
const void *info, u16 info_len)
|
||||
{
|
||||
void *temp;
|
||||
void *old_nol_info;
|
||||
struct cnss_dfs_nol_info *dfs_info;
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
|
||||
if (!priv)
|
||||
return -EINVAL;
|
||||
|
||||
if (!info || !info_len)
|
||||
return -EINVAL;
|
||||
|
||||
temp = kmemdup(info, info_len, GFP_ATOMIC);
|
||||
if (!temp)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_bh(&priv->dfs_nol_info_lock);
|
||||
dfs_info = &priv->dfs_nol_info;
|
||||
old_nol_info = dfs_info->dfs_nol_info;
|
||||
dfs_info->dfs_nol_info = temp;
|
||||
dfs_info->dfs_nol_info_len = info_len;
|
||||
spin_unlock_bh(&priv->dfs_nol_info_lock);
|
||||
kfree(old_nol_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_wlan_set_dfs_nol);
|
||||
|
||||
int cnss_utils_wlan_get_dfs_nol(struct device *dev,
|
||||
void *info, u16 info_len)
|
||||
{
|
||||
int len;
|
||||
struct cnss_dfs_nol_info *dfs_info;
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
|
||||
if (!priv)
|
||||
return -EINVAL;
|
||||
|
||||
if (!info || !info_len)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_bh(&priv->dfs_nol_info_lock);
|
||||
|
||||
dfs_info = &priv->dfs_nol_info;
|
||||
if (!dfs_info->dfs_nol_info ||
|
||||
dfs_info->dfs_nol_info_len == 0) {
|
||||
spin_unlock_bh(&priv->dfs_nol_info_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
len = min(info_len, dfs_info->dfs_nol_info_len);
|
||||
memcpy(info, dfs_info->dfs_nol_info, len);
|
||||
spin_unlock_bh(&priv->dfs_nol_info_lock);
|
||||
|
||||
return len;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_wlan_get_dfs_nol);
|
||||
|
||||
void cnss_utils_increment_driver_load_cnt(struct device *dev)
|
||||
{
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
++(priv->driver_load_cnt);
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_increment_driver_load_cnt);
|
||||
|
||||
int cnss_utils_get_driver_load_cnt(struct device *dev)
|
||||
{
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
|
||||
if (!priv)
|
||||
return -EINVAL;
|
||||
|
||||
return priv->driver_load_cnt;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_get_driver_load_cnt);
|
||||
|
||||
static int set_wlan_mac_address(const u8 *mac_list, const uint32_t len,
|
||||
enum mac_type type)
|
||||
{
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
u32 no_of_mac_addr;
|
||||
struct cnss_wlan_mac_addr *addr = NULL;
|
||||
int iter;
|
||||
u8 *temp = NULL;
|
||||
|
||||
if (!priv)
|
||||
return -EINVAL;
|
||||
|
||||
if (len == 0 || (len % ETH_ALEN) != 0) {
|
||||
pr_err("Invalid length %d\n", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
no_of_mac_addr = len / ETH_ALEN;
|
||||
if (no_of_mac_addr > MAX_NO_OF_MAC_ADDR) {
|
||||
pr_err("Exceed maximum supported MAC address %u %u\n",
|
||||
MAX_NO_OF_MAC_ADDR, no_of_mac_addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (type == CNSS_MAC_PROVISIONED)
|
||||
addr = &priv->wlan_mac_addr;
|
||||
else
|
||||
addr = &priv->wlan_der_mac_addr;
|
||||
|
||||
if (addr->no_of_mac_addr_set) {
|
||||
pr_err("WLAN MAC address is already set, num %d type %d\n",
|
||||
addr->no_of_mac_addr_set, type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr->no_of_mac_addr_set = no_of_mac_addr;
|
||||
temp = &addr->mac_addr[0][0];
|
||||
|
||||
for (iter = 0; iter < no_of_mac_addr;
|
||||
++iter, temp += ETH_ALEN, mac_list += ETH_ALEN) {
|
||||
ether_addr_copy(temp, mac_list);
|
||||
pr_debug("MAC_ADDR:%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
temp[0], temp[1], temp[2],
|
||||
temp[3], temp[4], temp[5]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_utils_set_wlan_mac_address(const u8 *mac_list, const uint32_t len)
|
||||
{
|
||||
return set_wlan_mac_address(mac_list, len, CNSS_MAC_PROVISIONED);
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_set_wlan_mac_address);
|
||||
|
||||
int cnss_utils_set_wlan_derived_mac_address(const u8 *mac_list,
|
||||
const uint32_t len)
|
||||
{
|
||||
return set_wlan_mac_address(mac_list, len, CNSS_MAC_DERIVED);
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_set_wlan_derived_mac_address);
|
||||
|
||||
static u8 *get_wlan_mac_address(struct device *dev,
|
||||
u32 *num, enum mac_type type)
|
||||
{
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
struct cnss_wlan_mac_addr *addr = NULL;
|
||||
|
||||
if (!priv)
|
||||
goto out;
|
||||
|
||||
if (type == CNSS_MAC_PROVISIONED)
|
||||
addr = &priv->wlan_mac_addr;
|
||||
else
|
||||
addr = &priv->wlan_der_mac_addr;
|
||||
|
||||
if (!addr->no_of_mac_addr_set) {
|
||||
pr_err("WLAN MAC address is not set, type %d\n", type);
|
||||
goto out;
|
||||
}
|
||||
*num = addr->no_of_mac_addr_set;
|
||||
return &addr->mac_addr[0][0];
|
||||
|
||||
out:
|
||||
*num = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u8 *cnss_utils_get_wlan_mac_address(struct device *dev, uint32_t *num)
|
||||
{
|
||||
return get_wlan_mac_address(dev, num, CNSS_MAC_PROVISIONED);
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_get_wlan_mac_address);
|
||||
|
||||
u8 *cnss_utils_get_wlan_derived_mac_address(struct device *dev,
|
||||
uint32_t *num)
|
||||
{
|
||||
return get_wlan_mac_address(dev, num, CNSS_MAC_DERIVED);
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_get_wlan_derived_mac_address);
|
||||
|
||||
void cnss_utils_set_cc_source(struct device *dev,
|
||||
enum cnss_utils_cc_src cc_source)
|
||||
{
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
priv->cc_source = cc_source;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_set_cc_source);
|
||||
|
||||
enum cnss_utils_cc_src cnss_utils_get_cc_source(struct device *dev)
|
||||
{
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
|
||||
if (!priv)
|
||||
return -EINVAL;
|
||||
|
||||
return priv->cc_source;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_get_cc_source);
|
||||
|
||||
#ifdef CONFIG_FEATURE_SMEM_MAILBOX
|
||||
int cnss_utils_smem_mailbox_write(struct device *dev, int flags,
|
||||
const __u8 *data, uint32_t len)
|
||||
{
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
|
||||
if (!priv)
|
||||
return -EINVAL;
|
||||
if (!priv->smem_mailbox_initialized) {
|
||||
if (smem_mailbox_start(priv->smem_mailbox_id, NULL) != 1) {
|
||||
pr_err("Didn't init smem mailbox properly\n");
|
||||
return -EINVAL;
|
||||
} else
|
||||
priv->smem_mailbox_initialized = true;
|
||||
}
|
||||
return smem_mailbox_write(priv->smem_mailbox_id, flags, (__u8 *)data,
|
||||
len);
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_utils_smem_mailbox_write);
|
||||
#endif
|
||||
|
||||
static ssize_t cnss_utils_mac_write(struct file *fp,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *off)
|
||||
{
|
||||
struct cnss_utils_priv *priv =
|
||||
((struct seq_file *)fp->private_data)->private;
|
||||
char buf[128];
|
||||
char *input, *mac_type, *mac_address;
|
||||
u8 *dest_mac;
|
||||
u8 val;
|
||||
const char *delim = "\n";
|
||||
size_t len = 0;
|
||||
char temp[3] = "";
|
||||
|
||||
len = min_t(size_t, count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EINVAL;
|
||||
buf[len] = '\0';
|
||||
|
||||
input = buf;
|
||||
|
||||
mac_type = strsep(&input, delim);
|
||||
if (!mac_type)
|
||||
return -EINVAL;
|
||||
if (!input)
|
||||
return -EINVAL;
|
||||
|
||||
mac_address = strsep(&input, delim);
|
||||
if (!mac_address)
|
||||
return -EINVAL;
|
||||
if (strcmp("0x", mac_address)) {
|
||||
pr_err("Invalid MAC prefix\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
len = strlen(mac_address);
|
||||
mac_address += MAC_PREFIX_LEN;
|
||||
len -= MAC_PREFIX_LEN;
|
||||
if (len < ETH_ALEN * 2 || len > ETH_ALEN * 2 * MAX_NO_OF_MAC_ADDR ||
|
||||
len % (ETH_ALEN * 2) != 0) {
|
||||
pr_err("Invalid MAC address length %zu\n", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!strcmp("provisioned", mac_type)) {
|
||||
dest_mac = &priv->wlan_mac_addr.mac_addr[0][0];
|
||||
priv->wlan_mac_addr.no_of_mac_addr_set = len / (ETH_ALEN * 2);
|
||||
} else if (!strcmp("derived", mac_type)) {
|
||||
dest_mac = &priv->wlan_der_mac_addr.mac_addr[0][0];
|
||||
priv->wlan_der_mac_addr.no_of_mac_addr_set =
|
||||
len / (ETH_ALEN * 2);
|
||||
} else {
|
||||
pr_err("Invalid MAC address type %s\n", mac_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (len--) {
|
||||
temp[0] = *mac_address++;
|
||||
temp[1] = *mac_address++;
|
||||
if (kstrtou8(temp, 16, &val))
|
||||
return -EINVAL;
|
||||
*dest_mac++ = val;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int cnss_utils_mac_show(struct seq_file *s, void *data)
|
||||
{
|
||||
u8 mac[6];
|
||||
int i;
|
||||
struct cnss_utils_priv *priv = s->private;
|
||||
struct cnss_wlan_mac_addr *addr = NULL;
|
||||
|
||||
addr = &priv->wlan_mac_addr;
|
||||
if (addr->no_of_mac_addr_set) {
|
||||
seq_puts(s, "\nProvisioned MAC addresseses\n");
|
||||
for (i = 0; i < addr->no_of_mac_addr_set; i++) {
|
||||
ether_addr_copy(mac, addr->mac_addr[i]);
|
||||
seq_printf(s, "MAC_ADDR:%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
mac[0], mac[1], mac[2],
|
||||
mac[3], mac[4], mac[5]);
|
||||
}
|
||||
}
|
||||
|
||||
addr = &priv->wlan_der_mac_addr;
|
||||
if (addr->no_of_mac_addr_set) {
|
||||
seq_puts(s, "\nDerived MAC addresseses\n");
|
||||
for (i = 0; i < addr->no_of_mac_addr_set; i++) {
|
||||
ether_addr_copy(mac, addr->mac_addr[i]);
|
||||
seq_printf(s, "MAC_ADDR:%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
mac[0], mac[1], mac[2],
|
||||
mac[3], mac[4], mac[5]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_utils_mac_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, cnss_utils_mac_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations cnss_utils_mac_fops = {
|
||||
.read = seq_read,
|
||||
.write = cnss_utils_mac_write,
|
||||
.release = single_release,
|
||||
.open = cnss_utils_mac_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static int cnss_utils_debugfs_create(struct cnss_utils_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
struct dentry *root_dentry;
|
||||
|
||||
root_dentry = debugfs_create_dir("cnss_utils", NULL);
|
||||
|
||||
if (IS_ERR(root_dentry)) {
|
||||
ret = PTR_ERR(root_dentry);
|
||||
pr_err("Unable to create debugfs %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
priv->root_dentry = root_dentry;
|
||||
debugfs_create_file("mac_address", 0600, root_dentry, priv,
|
||||
&cnss_utils_mac_fops);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_utils_is_valid_dt_node_found - Check if valid device tree node present
|
||||
*
|
||||
* Valid device tree node means a node with "qcom,wlan" property present and
|
||||
* "status" property not disabled.
|
||||
*
|
||||
* Return: true if valid device tree node found, false if not found
|
||||
*/
|
||||
static bool cnss_utils_is_valid_dt_node_found(void)
|
||||
{
|
||||
struct device_node *dn = NULL;
|
||||
|
||||
for_each_node_with_property(dn, "qcom,wlan") {
|
||||
if (of_device_is_available(dn))
|
||||
break;
|
||||
}
|
||||
|
||||
if (dn)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FEATURE_SMEM_MAILBOX
|
||||
static void cnss_utils_smem_mailbox_init(void)
|
||||
{
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
|
||||
priv->smem_mailbox_id = 0;
|
||||
priv->smem_mailbox_initialized = false;
|
||||
}
|
||||
|
||||
static void cnss_utils_smem_mailbox_deinit(void)
|
||||
{
|
||||
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||
|
||||
smem_mailbox_stop(priv->smem_mailbox_id);
|
||||
}
|
||||
#else
|
||||
static void cnss_utils_smem_mailbox_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void cnss_utils_smem_mailbox_deinit(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init cnss_utils_init(void)
|
||||
{
|
||||
struct cnss_utils_priv *priv = NULL;
|
||||
|
||||
if (!cnss_utils_is_valid_dt_node_found())
|
||||
return -ENODEV;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->cc_source = CNSS_UTILS_SOURCE_CORE;
|
||||
priv->cnss_device_type = CNSS_UNSUPPORETD_DEVICE_TYPE;
|
||||
|
||||
mutex_init(&priv->unsafe_channel_list_lock);
|
||||
mutex_init(&priv->cnss_device_id_lock);
|
||||
spin_lock_init(&priv->dfs_nol_info_lock);
|
||||
cnss_utils_debugfs_create(priv);
|
||||
cnss_utils_priv = priv;
|
||||
cnss_utils_smem_mailbox_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit cnss_utils_exit(void)
|
||||
{
|
||||
cnss_utils_smem_mailbox_deinit();
|
||||
kfree(cnss_utils_priv);
|
||||
cnss_utils_priv = NULL;
|
||||
}
|
||||
|
||||
module_init(cnss_utils_init);
|
||||
module_exit(cnss_utils_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("CNSS Utilities Driver");
|
@@ -0,0 +1,75 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#include <linux/soc/qcom/qmi.h>
|
||||
|
||||
#include "device_management_service_v01.h"
|
||||
|
||||
struct qmi_elem_info dms_get_mac_address_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_SIGNED_4_BYTE_ENUM,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(enum dms_device_mac_enum_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset = offsetof(struct
|
||||
dms_get_mac_address_req_msg_v01,
|
||||
device),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(dms_get_mac_address_req_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info dms_get_mac_address_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct
|
||||
dms_get_mac_address_resp_msg_v01,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct
|
||||
dms_get_mac_address_resp_msg_v01,
|
||||
mac_address_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_DATA_LEN,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct
|
||||
dms_get_mac_address_resp_msg_v01,
|
||||
mac_address_len),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = QMI_DMS_MAC_ADDR_MAX_V01,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = VAR_LEN_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct
|
||||
dms_get_mac_address_resp_msg_v01,
|
||||
mac_address),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(dms_get_mac_address_resp_msg_v01_ei);
|
@@ -0,0 +1,38 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef DEVICE_MANAGEMENT_SERVICE_V01_H
|
||||
#define DEVICE_MANAGEMENT_SERVICE_V01_H
|
||||
|
||||
#define DMS_SERVICE_ID_V01 0x02
|
||||
#define DMS_SERVICE_VERS_V01 0x01
|
||||
|
||||
#define QMI_DMS_GET_MAC_ADDRESS_RESP_V01 0x005C
|
||||
#define QMI_DMS_GET_MAC_ADDRESS_REQ_V01 0x005C
|
||||
#define QMI_DMS_MAC_ADDR_MAX_V01 8
|
||||
|
||||
enum dms_device_mac_enum_v01 {
|
||||
DMS_DEVICE_MAC_ENUM_MIN_VAL_V01 = INT_MIN,
|
||||
DMS_DEVICE_MAC_WLAN_V01 = 0,
|
||||
DMS_DEVICE_MAC_BT_V01 = 1,
|
||||
DMS_DEVICE_MAC_ENUM_MAX_VAL_V01 = INT_MAX,
|
||||
};
|
||||
|
||||
struct dms_get_mac_address_req_msg_v01 {
|
||||
enum dms_device_mac_enum_v01 device;
|
||||
};
|
||||
|
||||
#define DMS_GET_MAC_ADDRESS_REQ_MSG_V01_MAX_MSG_LEN 7
|
||||
extern struct qmi_elem_info dms_get_mac_address_req_msg_v01_ei[];
|
||||
|
||||
struct dms_get_mac_address_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
u8 mac_address_valid;
|
||||
u32 mac_address_len;
|
||||
u8 mac_address[QMI_DMS_MAC_ADDR_MAX_V01];
|
||||
};
|
||||
|
||||
#define DMS_GET_MAC_ADDRESS_RESP_MSG_V01_MAX_MSG_LEN 19
|
||||
extern struct qmi_elem_info dms_get_mac_address_resp_msg_v01_ei[];
|
||||
|
||||
#endif
|
@@ -0,0 +1,457 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "ip_multimedia_subsystem_private_service_v01.h"
|
||||
|
||||
static struct qmi_elem_info ims_private_service_header_value_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRING,
|
||||
.elem_len = IMS_PRIVATE_SERVICE_HEADER_STR_LEN_V01 + 1,
|
||||
.elem_size = sizeof(char),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_header_value_v01, header),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRING,
|
||||
.elem_len = IMS_PRIVATE_SERVICE_HEADER_STR_LEN_V01 + 1,
|
||||
.elem_size = sizeof(char),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_header_value_v01, value),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info
|
||||
ims_private_service_subscribe_ind_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct
|
||||
ims_private_service_subscribe_for_indications_req_msg_v01,
|
||||
mt_invite_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct
|
||||
ims_private_service_subscribe_for_indications_req_msg_v01,
|
||||
mt_invite),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(struct
|
||||
ims_private_service_subscribe_for_indications_req_msg_v01,
|
||||
wfc_call_status_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(struct
|
||||
ims_private_service_subscribe_for_indications_req_msg_v01,
|
||||
wfc_call_status),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(ims_private_service_subscribe_ind_req_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info
|
||||
ims_private_service_subscribe_ind_rsp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct
|
||||
ims_private_service_subscribe_for_indications_rsp_msg_v01,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(ims_private_service_subscribe_ind_rsp_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info ims_private_service_mt_invite_ind_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_SIGNED_4_BYTE_ENUM,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(enum ims_subscription_type_enum_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_mt_invite_ind_msg_v01,
|
||||
subscription_type),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_mt_invite_ind_msg_v01,
|
||||
iccid_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRING,
|
||||
.elem_len = IMS_PRIVATE_SERVICE_MAX_ICCID_LEN_V01 + 1,
|
||||
.elem_size = sizeof(char),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_mt_invite_ind_msg_v01,
|
||||
iccid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_mt_invite_ind_msg_v01,
|
||||
header_value_list_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_DATA_LEN,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_mt_invite_ind_msg_v01,
|
||||
header_value_list_len),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = IMS_PRIVATE_SERVICE_MAX_MT_INVITE_HEADERS_V01,
|
||||
.elem_size =
|
||||
sizeof(struct ims_private_service_header_value_v01),
|
||||
.array_type = VAR_LEN_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_mt_invite_ind_msg_v01,
|
||||
header_value_list),
|
||||
.ei_array = ims_private_service_header_value_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(ims_private_service_mt_invite_ind_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info ims_private_service_wfc_call_status_ind_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_wfc_call_status_ind_msg_v01,
|
||||
wfc_call_active),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_wfc_call_status_ind_msg_v01,
|
||||
all_wfc_calls_held_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_wfc_call_status_ind_msg_v01,
|
||||
all_wfc_calls_held),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_wfc_call_status_ind_msg_v01,
|
||||
is_wfc_emergency_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_wfc_call_status_ind_msg_v01,
|
||||
is_wfc_emergency),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x12,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_wfc_call_status_ind_msg_v01,
|
||||
twt_ims_start_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u64),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x12,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_wfc_call_status_ind_msg_v01,
|
||||
twt_ims_start),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x13,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_wfc_call_status_ind_msg_v01,
|
||||
twt_ims_int_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_2_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u16),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x13,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_wfc_call_status_ind_msg_v01,
|
||||
twt_ims_int),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x14,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_wfc_call_status_ind_msg_v01,
|
||||
media_quality_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_SIGNED_4_BYTE_ENUM,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(enum wfc_media_quality_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x14,
|
||||
.offset =
|
||||
offsetof(struct ims_private_service_wfc_call_status_ind_msg_v01,
|
||||
media_quality),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(ims_private_service_wfc_call_status_ind_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset =
|
||||
offsetof(struct
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01,
|
||||
twt_sta_start_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u64),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset =
|
||||
offsetof(struct
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01,
|
||||
twt_sta_start),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset =
|
||||
offsetof(struct
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01,
|
||||
twt_sta_int_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_2_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u16),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset =
|
||||
offsetof(struct
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01,
|
||||
twt_sta_int),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x12,
|
||||
.offset =
|
||||
offsetof(struct
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01,
|
||||
twt_sta_upo_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_2_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u16),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x12,
|
||||
.offset =
|
||||
offsetof(struct
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01,
|
||||
twt_sta_upo),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x13,
|
||||
.offset =
|
||||
offsetof(struct
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01,
|
||||
twt_sta_sp_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_2_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u16),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x13,
|
||||
.offset =
|
||||
offsetof(struct
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01,
|
||||
twt_sta_sp),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x14,
|
||||
.offset =
|
||||
offsetof(struct
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01,
|
||||
twt_sta_dl_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_2_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u16),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x14,
|
||||
.offset =
|
||||
offsetof(struct
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01,
|
||||
twt_sta_dl),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x15,
|
||||
.offset =
|
||||
offsetof(struct
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01,
|
||||
twt_sta_config_changed_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x15,
|
||||
.offset =
|
||||
offsetof(struct
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01,
|
||||
twt_sta_config_changed),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(ims_private_service_wfc_call_twt_config_req_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info
|
||||
ims_private_service_wfc_call_twt_config_rsp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset =
|
||||
offsetof(struct
|
||||
ims_private_service_wfc_call_twt_config_rsp_msg_v01,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(ims_private_service_wfc_call_twt_config_rsp_msg_v01_ei);
|
@@ -0,0 +1,136 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef IP_MULTIMEDIA_SUBSYSTEM_PRIVATE_SERVICE_V01_H
|
||||
#define IP_MULTIMEDIA_SUBSYSTEM_PRIVATE_SERVICE_V01_H
|
||||
|
||||
#include <linux/soc/qcom/qmi.h>
|
||||
|
||||
#define IMSPRIVATE_SERVICE_ID_V01 0x4D
|
||||
#define IMSPRIVATE_SERVICE_VERS_V01 0x01
|
||||
|
||||
#define QMI_IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_RSP_V01 0x003E
|
||||
#define QMI_IMS_PRIVATE_SERVICE_WFC_CALL_STATUS_IND_V01 0x0040
|
||||
#define QMI_IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_REQ_V01 0x003E
|
||||
#define QMI_IMS_PRIVATE_SERVICE_MT_INVITE_IND_V01 0x003F
|
||||
#define QMI_IMS_PRIVATE_SERVICE_WFC_CALL_TWT_CONFIG_RSP_V01 0x0041
|
||||
#define QMI_IMS_PRIVATE_SERVICE_WFC_CALL_TWT_CONFIG_REQ_V01 0x0041
|
||||
|
||||
#define IMS_PRIVATE_SERVICE_MAX_MT_INVITE_HEADERS_V01 15
|
||||
#define IMS_PRIVATE_SERVICE_HEADER_STR_LEN_V01 1024
|
||||
#define IMS_PRIVATE_SERVICE_MAX_ICCID_LEN_V01 21
|
||||
|
||||
enum ims_common_resp_enum_v01 {
|
||||
IMS_COMMON_RESP_ENUM_MIN_VAL_V01 = INT_MIN,
|
||||
IMS_COMMON_MSG_NO_ERR_V01 = 0,
|
||||
IMS_COMMON_MSG_IMS_NOT_READY_V01 = 1,
|
||||
IMS_COMMON_MSG_FILE_NOT_AVAILABLE_V01 = 2,
|
||||
IMS_COMMON_MSG_READ_FAILED_V01 = 3,
|
||||
IMS_COMMON_MSG_WRITE_FAILED_V01 = 4,
|
||||
IMS_COMMON_MSG_OTHER_INTERNAL_ERR_V01 = 5,
|
||||
IMS_COMMON_RESP_ENUM_MAX_VAL_V01 = INT_MAX,
|
||||
};
|
||||
|
||||
enum ims_subscription_type_enum_v01 {
|
||||
IMS_SUBSCRIPTION_TYPE_ENUM_MIN_VAL_V01 = INT_MIN,
|
||||
IMS_SUBSCRIPTION_TYPE_NONE_V01 = -1,
|
||||
IMS_SUBSCRIPTION_TYPE_PRIMARY_V01 = 0,
|
||||
IMS_SUBSCRIPTION_TYPE_SECONDARY_V01 = 1,
|
||||
IMS_SUBSCRIPTION_TYPE_TERTIARY_V01 = 2,
|
||||
IMS_SUBSCRIPTION_TYPE_ENUM_MAX_VAL_V01 = INT_MAX,
|
||||
};
|
||||
|
||||
enum wfc_media_quality_v01 {
|
||||
WFC_MEDIA_QUALITY_MIN_VAL_V01 = INT_MIN,
|
||||
WFC_MEDIA_QUAL_NOT_AVAILABLE_V01 = 0,
|
||||
WFC_MEDIA_QUAL_BAD_V01 = 1,
|
||||
WFC_MEDIA_QUAL_GOOD_V01 = 2,
|
||||
WFC_MEDIA_QUAL_EXCELLENT_V01 = 3,
|
||||
WFC_MEDIA_QUALITY_MAX_VAL_V01 = INT_MAX,
|
||||
};
|
||||
|
||||
struct ims_private_service_header_value_v01 {
|
||||
char header[IMS_PRIVATE_SERVICE_HEADER_STR_LEN_V01 + 1];
|
||||
char value[IMS_PRIVATE_SERVICE_HEADER_STR_LEN_V01 + 1];
|
||||
};
|
||||
|
||||
struct ims_private_service_subscribe_for_indications_req_msg_v01 {
|
||||
u8 mt_invite_valid;
|
||||
u8 mt_invite;
|
||||
u8 wfc_call_status_valid;
|
||||
u8 wfc_call_status;
|
||||
};
|
||||
|
||||
#define IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_REQ_MSG_V01_MAX_MSG_LEN 8
|
||||
extern struct qmi_elem_info
|
||||
ims_private_service_subscribe_ind_req_msg_v01_ei[];
|
||||
|
||||
struct ims_private_service_subscribe_for_indications_rsp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
|
||||
#define IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_RSP_MSG_V01_MAX_MSG_LEN 7
|
||||
extern struct qmi_elem_info
|
||||
ims_private_service_subscribe_ind_rsp_msg_v01_ei[];
|
||||
|
||||
struct ims_private_service_mt_invite_ind_msg_v01 {
|
||||
enum ims_subscription_type_enum_v01 subscription_type;
|
||||
u8 iccid_valid;
|
||||
char iccid[IMS_PRIVATE_SERVICE_MAX_ICCID_LEN_V01 + 1];
|
||||
u8 header_value_list_valid;
|
||||
u32 header_value_list_len;
|
||||
struct ims_private_service_header_value_v01
|
||||
header_value_list[IMS_PRIVATE_SERVICE_MAX_MT_INVITE_HEADERS_V01];
|
||||
};
|
||||
|
||||
#define IMS_PRIVATE_SERVICE_MT_INVITE_IND_MSG_V01_MAX_MSG_LEN 30815
|
||||
extern struct qmi_elem_info ims_private_service_mt_invite_ind_msg_v01_ei[];
|
||||
|
||||
struct ims_private_service_wfc_call_status_ind_msg_v01 {
|
||||
u8 wfc_call_active;
|
||||
u8 all_wfc_calls_held_valid;
|
||||
u8 all_wfc_calls_held;
|
||||
u8 is_wfc_emergency_valid;
|
||||
u8 is_wfc_emergency;
|
||||
u8 twt_ims_start_valid;
|
||||
u64 twt_ims_start;
|
||||
u8 twt_ims_int_valid;
|
||||
u16 twt_ims_int;
|
||||
u8 media_quality_valid;
|
||||
enum wfc_media_quality_v01 media_quality;
|
||||
};
|
||||
|
||||
#define IMS_PRIVATE_SERVICE_WFC_CALL_STATUS_IND_MSG_V01_MAX_MSG_LEN 35
|
||||
extern struct qmi_elem_info
|
||||
ims_private_service_wfc_call_status_ind_msg_v01_ei[];
|
||||
|
||||
struct ims_private_service_wfc_call_twt_config_req_msg_v01 {
|
||||
u8 twt_sta_start_valid;
|
||||
u64 twt_sta_start;
|
||||
u8 twt_sta_int_valid;
|
||||
u16 twt_sta_int;
|
||||
u8 twt_sta_upo_valid;
|
||||
u16 twt_sta_upo;
|
||||
u8 twt_sta_sp_valid;
|
||||
u16 twt_sta_sp;
|
||||
u8 twt_sta_dl_valid;
|
||||
u16 twt_sta_dl;
|
||||
u8 twt_sta_config_changed_valid;
|
||||
u8 twt_sta_config_changed;
|
||||
};
|
||||
|
||||
#define IMS_PRIVATE_SERVICE_WFC_CALL_TWT_CONFIG_REQ_MSG_V01_MAX_MSG_LEN 35
|
||||
extern struct qmi_elem_info
|
||||
ims_private_service_wfc_call_twt_config_req_msg_v01_ei[];
|
||||
|
||||
struct ims_private_service_wfc_call_twt_config_rsp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
|
||||
#define IMS_PRIVATE_SERVICE_WFC_CALL_TWT_CONFIG_RSP_MSG_V01_MAX_MSG_LEN 7
|
||||
extern struct qmi_elem_info
|
||||
ims_private_service_wfc_call_twt_config_rsp_msg_v01_ei[];
|
||||
|
||||
#endif
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,4 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,4 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,4 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,4 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,4 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,4 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_QMI_SVC=m
|
||||
CONFIG_CNSS_OUT_OF_TREE=y
|
文件差异内容过多而无法显示
加载差异
文件差异内容过多而无法显示
加载差异
某些文件未显示,因为此 diff 中更改的文件太多 显示更多
在新工单中引用
屏蔽一个用户