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
这个提交包含在:
David Wronek
2024-10-06 16:46:09 +02:00
当前提交 925e49bf4f
修改 128 个文件,包含 52890 行新增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()

查看文件

@@ -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 中更改的文件太多 显示更多