wlan_platform: Bring initial files for CNSS family drivers
Bring CNSS family drivers from msm-5.10 kernel as of commit cc3bc4b888af (cnss2: Fix a few switch statement fallthrough issues) to WLAN platform project. Fix SPDX-License format for a few files as well. drivers/net/wireless/cnss* -> . include/net/cnss* -> inc/ Above shows how directories and header files are relocated. Change-Id: If8fd40a35c9fdbeb1aa76a8aac5fdb1fc1c7e786
This commit is contained in:
107
cnss2/Kconfig
Normal file
107
cnss2/Kconfig
Normal file
@@ -0,0 +1,107 @@
|
||||
# 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_WCN7850
|
||||
bool "Enable CNSS WCN7850 chipset specific changes"
|
||||
depends on CNSS2
|
||||
help
|
||||
This enables the changes from WLAN host driver that are specific to
|
||||
CNSS WCN7850 chipset.
|
||||
These changes are needed to support the new hardware architecture
|
||||
for CNSS WCN7850 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.
|
12
cnss2/Makefile
Normal file
12
cnss2/Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_CNSS2) += cnss2.o
|
||||
|
||||
ccflags-y += -I$(srctree)/drivers/net/wireless/cnss_utils/
|
||||
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_CNSS2_QMI) += qmi.o coexistence_service_v01.o ip_multimedia_subsystem_private_service_v01.o
|
564
cnss2/bus.c
Normal file
564
cnss2/bus.c
Normal file
@@ -0,0 +1,564 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#include "bus.h"
|
||||
#include "debug.h"
|
||||
#include "pci.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(unsigned long device_id)
|
||||
{
|
||||
switch (device_id) {
|
||||
case QCA6174_DEVICE_ID:
|
||||
case QCA6290_DEVICE_ID:
|
||||
case QCA6390_DEVICE_ID:
|
||||
case QCA6490_DEVICE_ID:
|
||||
case WCN7850_DEVICE_ID:
|
||||
return CNSS_BUS_PCI;
|
||||
default:
|
||||
cnss_pr_err("Unknown device_id: 0x%lx\n", 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_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_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_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_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;
|
||||
}
|
||||
}
|
67
cnss2/bus.h
Normal file
67
cnss2/bus.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef _CNSS_BUS_H
|
||||
#define _CNSS_BUS_H
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#define QCA6174_VENDOR_ID 0x168C
|
||||
#define QCA6174_DEVICE_ID 0x003E
|
||||
#define QCA6174_REV_ID_OFFSET 0x08
|
||||
#define QCA6174_REV3_VERSION 0x5020000
|
||||
#define QCA6174_REV3_2_VERSION 0x5030000
|
||||
#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 WCN7850_VENDOR_ID 0x17CB
|
||||
#define WCN7850_DEVICE_ID 0x1107
|
||||
|
||||
enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev);
|
||||
enum cnss_dev_bus_type cnss_get_bus_type(unsigned long device_id);
|
||||
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_m3(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_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);
|
||||
#endif /* _CNSS_BUS_H */
|
100
cnss2/coexistence_service_v01.c
Normal file
100
cnss2/coexistence_service_v01.c
Normal file
@@ -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,
|
||||
},
|
||||
};
|
52
cnss2/coexistence_service_v01.h
Normal file
52
cnss2/coexistence_service_v01.h
Normal file
@@ -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
|
973
cnss2/debug.c
Normal file
973
cnss2/debug.c
Normal file
@@ -0,0 +1,973 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include "main.h"
|
||||
#include "bus.h"
|
||||
#include "debug.h"
|
||||
#include "pci.h"
|
||||
|
||||
#define MMIO_REG_ACCESS_MEM_TYPE 0xFF
|
||||
#define MMIO_REG_RAW_ACCESS_MEM_TYPE 0xFE
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPC_LOGGING)
|
||||
void *cnss_ipc_log_context;
|
||||
void *cnss_ipc_log_long_context;
|
||||
#endif
|
||||
|
||||
static int cnss_pin_connect_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct cnss_plat_data *cnss_priv = s->private;
|
||||
|
||||
seq_puts(s, "Pin connect results\n");
|
||||
seq_printf(s, "FW power pin result: %04x\n",
|
||||
cnss_priv->pin_result.fw_pwr_pin_result);
|
||||
seq_printf(s, "FW PHY IO pin result: %04x\n",
|
||||
cnss_priv->pin_result.fw_phy_io_pin_result);
|
||||
seq_printf(s, "FW RF pin result: %04x\n",
|
||||
cnss_priv->pin_result.fw_rf_pin_result);
|
||||
seq_printf(s, "Host pin result: %04x\n",
|
||||
cnss_priv->pin_result.host_pin_result);
|
||||
seq_puts(s, "\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_pin_connect_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, cnss_pin_connect_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations cnss_pin_connect_fops = {
|
||||
.read = seq_read,
|
||||
.release = single_release,
|
||||
.open = cnss_pin_connect_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static int cnss_stats_show_state(struct seq_file *s,
|
||||
struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
enum cnss_driver_state i;
|
||||
int skip = 0;
|
||||
unsigned long state;
|
||||
|
||||
seq_printf(s, "\nState: 0x%lx(", plat_priv->driver_state);
|
||||
for (i = 0, state = plat_priv->driver_state; state != 0;
|
||||
state >>= 1, i++) {
|
||||
if (!(state & 0x1))
|
||||
continue;
|
||||
|
||||
if (skip++)
|
||||
seq_puts(s, " | ");
|
||||
|
||||
switch (i) {
|
||||
case CNSS_QMI_WLFW_CONNECTED:
|
||||
seq_puts(s, "QMI_WLFW_CONNECTED");
|
||||
continue;
|
||||
case CNSS_FW_MEM_READY:
|
||||
seq_puts(s, "FW_MEM_READY");
|
||||
continue;
|
||||
case CNSS_FW_READY:
|
||||
seq_puts(s, "FW_READY");
|
||||
continue;
|
||||
case CNSS_IN_COLD_BOOT_CAL:
|
||||
seq_puts(s, "IN_COLD_BOOT_CAL");
|
||||
continue;
|
||||
case CNSS_DRIVER_LOADING:
|
||||
seq_puts(s, "DRIVER_LOADING");
|
||||
continue;
|
||||
case CNSS_DRIVER_UNLOADING:
|
||||
seq_puts(s, "DRIVER_UNLOADING");
|
||||
continue;
|
||||
case CNSS_DRIVER_IDLE_RESTART:
|
||||
seq_puts(s, "IDLE_RESTART");
|
||||
continue;
|
||||
case CNSS_DRIVER_IDLE_SHUTDOWN:
|
||||
seq_puts(s, "IDLE_SHUTDOWN");
|
||||
continue;
|
||||
case CNSS_DRIVER_PROBED:
|
||||
seq_puts(s, "DRIVER_PROBED");
|
||||
continue;
|
||||
case CNSS_DRIVER_RECOVERY:
|
||||
seq_puts(s, "DRIVER_RECOVERY");
|
||||
continue;
|
||||
case CNSS_FW_BOOT_RECOVERY:
|
||||
seq_puts(s, "FW_BOOT_RECOVERY");
|
||||
continue;
|
||||
case CNSS_DEV_ERR_NOTIFY:
|
||||
seq_puts(s, "DEV_ERR");
|
||||
continue;
|
||||
case CNSS_DRIVER_DEBUG:
|
||||
seq_puts(s, "DRIVER_DEBUG");
|
||||
continue;
|
||||
case CNSS_COEX_CONNECTED:
|
||||
seq_puts(s, "COEX_CONNECTED");
|
||||
continue;
|
||||
case CNSS_IMS_CONNECTED:
|
||||
seq_puts(s, "IMS_CONNECTED");
|
||||
continue;
|
||||
case CNSS_IN_SUSPEND_RESUME:
|
||||
seq_puts(s, "IN_SUSPEND_RESUME");
|
||||
continue;
|
||||
case CNSS_IN_REBOOT:
|
||||
seq_puts(s, "IN_REBOOT");
|
||||
continue;
|
||||
case CNSS_COLD_BOOT_CAL_DONE:
|
||||
seq_puts(s, "COLD_BOOT_CAL_DONE");
|
||||
continue;
|
||||
case CNSS_IN_PANIC:
|
||||
seq_puts(s, "IN_PANIC");
|
||||
continue;
|
||||
case CNSS_QMI_DEL_SERVER:
|
||||
seq_puts(s, "DEL_SERVER_IN_PROGRESS");
|
||||
continue;
|
||||
case CNSS_QMI_DMS_CONNECTED:
|
||||
seq_puts(s, "DMS_CONNECTED");
|
||||
continue;
|
||||
case CNSS_DAEMON_CONNECTED:
|
||||
seq_puts(s, "DAEMON_CONNECTED");
|
||||
continue;
|
||||
case CNSS_PCI_PROBE_DONE:
|
||||
seq_puts(s, "PCI PROBE DONE");
|
||||
continue;
|
||||
}
|
||||
|
||||
seq_printf(s, "UNKNOWN-%d", i);
|
||||
}
|
||||
seq_puts(s, ")\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_stats_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv = s->private;
|
||||
|
||||
cnss_stats_show_state(s, plat_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_stats_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, cnss_stats_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations cnss_stats_fops = {
|
||||
.read = seq_read,
|
||||
.release = single_release,
|
||||
.open = cnss_stats_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static ssize_t cnss_dev_boot_debug_write(struct file *fp,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *off)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv =
|
||||
((struct seq_file *)fp->private_data)->private;
|
||||
struct cnss_pci_data *pci_priv;
|
||||
char buf[64];
|
||||
char *cmd;
|
||||
unsigned int len = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
cmd = buf;
|
||||
cnss_pr_dbg("Received dev_boot debug command: %s\n", cmd);
|
||||
|
||||
if (sysfs_streq(cmd, "on")) {
|
||||
ret = cnss_power_on_device(plat_priv);
|
||||
} else if (sysfs_streq(cmd, "off")) {
|
||||
cnss_power_off_device(plat_priv);
|
||||
} else if (sysfs_streq(cmd, "enumerate")) {
|
||||
ret = cnss_pci_init(plat_priv);
|
||||
} else if (sysfs_streq(cmd, "powerup")) {
|
||||
set_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
|
||||
ret = cnss_driver_event_post(plat_priv,
|
||||
CNSS_DRIVER_EVENT_POWER_UP,
|
||||
CNSS_EVENT_SYNC, NULL);
|
||||
} else if (sysfs_streq(cmd, "shutdown")) {
|
||||
ret = cnss_driver_event_post(plat_priv,
|
||||
CNSS_DRIVER_EVENT_POWER_DOWN,
|
||||
0, NULL);
|
||||
clear_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
|
||||
} else {
|
||||
pci_priv = plat_priv->bus_priv;
|
||||
if (!pci_priv)
|
||||
return -ENODEV;
|
||||
|
||||
if (sysfs_streq(cmd, "download")) {
|
||||
set_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
|
||||
ret = cnss_pci_start_mhi(pci_priv);
|
||||
} else if (sysfs_streq(cmd, "linkup")) {
|
||||
ret = cnss_resume_pci_link(pci_priv);
|
||||
} else if (sysfs_streq(cmd, "linkdown")) {
|
||||
ret = cnss_suspend_pci_link(pci_priv);
|
||||
} else if (sysfs_streq(cmd, "assert")) {
|
||||
cnss_pr_info("FW Assert triggered for debug\n");
|
||||
ret = cnss_force_fw_assert(&pci_priv->pci_dev->dev);
|
||||
} else if (sysfs_streq(cmd, "set_cbc_done")) {
|
||||
cnss_pr_dbg("Force set cold boot cal done status\n");
|
||||
set_bit(CNSS_COLD_BOOT_CAL_DONE,
|
||||
&plat_priv->driver_state);
|
||||
} else {
|
||||
cnss_pr_err("Device boot debugfs command is invalid\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int cnss_dev_boot_debug_show(struct seq_file *s, void *data)
|
||||
{
|
||||
seq_puts(s, "\nUsage: echo <action> > <debugfs_path>/cnss/dev_boot\n");
|
||||
seq_puts(s, "<action> can be one of below:\n");
|
||||
seq_puts(s, "on: turn on device power, assert WLAN_EN\n");
|
||||
seq_puts(s, "off: de-assert WLAN_EN, turn off device power\n");
|
||||
seq_puts(s, "enumerate: de-assert PERST, enumerate PCIe\n");
|
||||
seq_puts(s, "download: download FW and do QMI handshake with FW\n");
|
||||
seq_puts(s, "linkup: bring up PCIe link\n");
|
||||
seq_puts(s, "linkdown: bring down PCIe link\n");
|
||||
seq_puts(s, "powerup: full power on sequence to boot device, download FW and do QMI handshake with FW\n");
|
||||
seq_puts(s, "shutdown: full power off sequence to shutdown device\n");
|
||||
seq_puts(s, "assert: trigger firmware assert\n");
|
||||
seq_puts(s, "set_cbc_done: Set cold boot calibration done status\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_dev_boot_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, cnss_dev_boot_debug_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations cnss_dev_boot_debug_fops = {
|
||||
.read = seq_read,
|
||||
.write = cnss_dev_boot_debug_write,
|
||||
.release = single_release,
|
||||
.open = cnss_dev_boot_debug_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static int cnss_reg_read_debug_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv = s->private;
|
||||
|
||||
mutex_lock(&plat_priv->dev_lock);
|
||||
if (!plat_priv->diag_reg_read_buf) {
|
||||
seq_puts(s, "\nUsage: echo <mem_type> <offset> <data_len> > <debugfs_path>/cnss/reg_read\n");
|
||||
seq_puts(s, "Use mem_type = 0xff for register read by IO access, data_len will be ignored\n");
|
||||
seq_puts(s, "Use mem_type = 0xfe for register read by raw IO access which skips sanity checks, data_len will be ignored\n");
|
||||
seq_puts(s, "Use other mem_type for register read by QMI\n");
|
||||
mutex_unlock(&plat_priv->dev_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
seq_printf(s, "\nRegister read, address: 0x%x memory type: 0x%x length: 0x%x\n\n",
|
||||
plat_priv->diag_reg_read_addr,
|
||||
plat_priv->diag_reg_read_mem_type,
|
||||
plat_priv->diag_reg_read_len);
|
||||
|
||||
seq_hex_dump(s, "", DUMP_PREFIX_OFFSET, 32, 4,
|
||||
plat_priv->diag_reg_read_buf,
|
||||
plat_priv->diag_reg_read_len, false);
|
||||
|
||||
plat_priv->diag_reg_read_len = 0;
|
||||
kfree(plat_priv->diag_reg_read_buf);
|
||||
plat_priv->diag_reg_read_buf = NULL;
|
||||
mutex_unlock(&plat_priv->dev_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t cnss_reg_read_debug_write(struct file *fp,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *off)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv =
|
||||
((struct seq_file *)fp->private_data)->private;
|
||||
char buf[64];
|
||||
char *sptr, *token;
|
||||
unsigned int len = 0;
|
||||
u32 reg_offset, mem_type;
|
||||
u32 data_len = 0, reg_val = 0;
|
||||
u8 *reg_buf = NULL;
|
||||
const char *delim = " ";
|
||||
int ret = 0;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
sptr = buf;
|
||||
|
||||
token = strsep(&sptr, delim);
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
if (!sptr)
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtou32(token, 0, &mem_type))
|
||||
return -EINVAL;
|
||||
|
||||
token = strsep(&sptr, delim);
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
if (!sptr)
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtou32(token, 0, ®_offset))
|
||||
return -EINVAL;
|
||||
|
||||
token = strsep(&sptr, delim);
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtou32(token, 0, &data_len))
|
||||
return -EINVAL;
|
||||
|
||||
if (mem_type == MMIO_REG_ACCESS_MEM_TYPE ||
|
||||
mem_type == MMIO_REG_RAW_ACCESS_MEM_TYPE) {
|
||||
ret = cnss_bus_debug_reg_read(plat_priv, reg_offset, ®_val,
|
||||
mem_type ==
|
||||
MMIO_REG_RAW_ACCESS_MEM_TYPE);
|
||||
if (ret)
|
||||
return ret;
|
||||
cnss_pr_dbg("Read 0x%x from register offset 0x%x\n", reg_val,
|
||||
reg_offset);
|
||||
return count;
|
||||
}
|
||||
|
||||
if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
|
||||
cnss_pr_err("Firmware is not ready yet\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&plat_priv->dev_lock);
|
||||
kfree(plat_priv->diag_reg_read_buf);
|
||||
plat_priv->diag_reg_read_buf = NULL;
|
||||
|
||||
reg_buf = kzalloc(data_len, GFP_KERNEL);
|
||||
if (!reg_buf) {
|
||||
mutex_unlock(&plat_priv->dev_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = cnss_wlfw_athdiag_read_send_sync(plat_priv, reg_offset,
|
||||
mem_type, data_len,
|
||||
reg_buf);
|
||||
if (ret) {
|
||||
kfree(reg_buf);
|
||||
mutex_unlock(&plat_priv->dev_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
plat_priv->diag_reg_read_addr = reg_offset;
|
||||
plat_priv->diag_reg_read_mem_type = mem_type;
|
||||
plat_priv->diag_reg_read_len = data_len;
|
||||
plat_priv->diag_reg_read_buf = reg_buf;
|
||||
mutex_unlock(&plat_priv->dev_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int cnss_reg_read_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, cnss_reg_read_debug_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations cnss_reg_read_debug_fops = {
|
||||
.read = seq_read,
|
||||
.write = cnss_reg_read_debug_write,
|
||||
.open = cnss_reg_read_debug_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static int cnss_reg_write_debug_show(struct seq_file *s, void *data)
|
||||
{
|
||||
seq_puts(s, "\nUsage: echo <mem_type> <offset> <reg_val> > <debugfs_path>/cnss/reg_write\n");
|
||||
seq_puts(s, "Use mem_type = 0xff for register write by IO access\n");
|
||||
seq_puts(s, "Use mem_type = 0xfe for register write by raw IO access which skips sanity checks\n");
|
||||
seq_puts(s, "Use other mem_type for register write by QMI\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t cnss_reg_write_debug_write(struct file *fp,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *off)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv =
|
||||
((struct seq_file *)fp->private_data)->private;
|
||||
char buf[64];
|
||||
char *sptr, *token;
|
||||
unsigned int len = 0;
|
||||
u32 reg_offset, mem_type, reg_val;
|
||||
const char *delim = " ";
|
||||
int ret = 0;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
sptr = buf;
|
||||
|
||||
token = strsep(&sptr, delim);
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
if (!sptr)
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtou32(token, 0, &mem_type))
|
||||
return -EINVAL;
|
||||
|
||||
token = strsep(&sptr, delim);
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
if (!sptr)
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtou32(token, 0, ®_offset))
|
||||
return -EINVAL;
|
||||
|
||||
token = strsep(&sptr, delim);
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtou32(token, 0, ®_val))
|
||||
return -EINVAL;
|
||||
|
||||
if (mem_type == MMIO_REG_ACCESS_MEM_TYPE ||
|
||||
mem_type == MMIO_REG_RAW_ACCESS_MEM_TYPE) {
|
||||
ret = cnss_bus_debug_reg_write(plat_priv, reg_offset, reg_val,
|
||||
mem_type ==
|
||||
MMIO_REG_RAW_ACCESS_MEM_TYPE);
|
||||
if (ret)
|
||||
return ret;
|
||||
cnss_pr_dbg("Wrote 0x%x to register offset 0x%x\n", reg_val,
|
||||
reg_offset);
|
||||
return count;
|
||||
}
|
||||
|
||||
if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
|
||||
cnss_pr_err("Firmware is not ready yet\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = cnss_wlfw_athdiag_write_send_sync(plat_priv, reg_offset, mem_type,
|
||||
sizeof(u32),
|
||||
(u8 *)®_val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int cnss_reg_write_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, cnss_reg_write_debug_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations cnss_reg_write_debug_fops = {
|
||||
.read = seq_read,
|
||||
.write = cnss_reg_write_debug_write,
|
||||
.open = cnss_reg_write_debug_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static ssize_t cnss_runtime_pm_debug_write(struct file *fp,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *off)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv =
|
||||
((struct seq_file *)fp->private_data)->private;
|
||||
struct cnss_pci_data *pci_priv;
|
||||
char buf[64];
|
||||
char *cmd;
|
||||
unsigned int len = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
pci_priv = plat_priv->bus_priv;
|
||||
if (!pci_priv)
|
||||
return -ENODEV;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
cmd = buf;
|
||||
|
||||
if (sysfs_streq(cmd, "usage_count")) {
|
||||
cnss_pci_pm_runtime_show_usage_count(pci_priv);
|
||||
} else if (sysfs_streq(cmd, "request_resume")) {
|
||||
ret = cnss_pci_pm_request_resume(pci_priv);
|
||||
} else if (sysfs_streq(cmd, "resume")) {
|
||||
ret = cnss_pci_pm_runtime_resume(pci_priv);
|
||||
} else if (sysfs_streq(cmd, "get")) {
|
||||
ret = cnss_pci_pm_runtime_get(pci_priv, RTPM_ID_CNSS);
|
||||
} else if (sysfs_streq(cmd, "get_noresume")) {
|
||||
cnss_pci_pm_runtime_get_noresume(pci_priv, RTPM_ID_CNSS);
|
||||
} else if (sysfs_streq(cmd, "put_autosuspend")) {
|
||||
ret = cnss_pci_pm_runtime_put_autosuspend(pci_priv,
|
||||
RTPM_ID_CNSS);
|
||||
} else if (sysfs_streq(cmd, "put_noidle")) {
|
||||
cnss_pci_pm_runtime_put_noidle(pci_priv, RTPM_ID_CNSS);
|
||||
} else if (sysfs_streq(cmd, "mark_last_busy")) {
|
||||
cnss_pci_pm_runtime_mark_last_busy(pci_priv);
|
||||
} else if (sysfs_streq(cmd, "resume_bus")) {
|
||||
cnss_pci_resume_bus(pci_priv);
|
||||
} else if (sysfs_streq(cmd, "suspend_bus")) {
|
||||
cnss_pci_suspend_bus(pci_priv);
|
||||
} else {
|
||||
cnss_pr_err("Runtime PM debugfs command is invalid\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int cnss_runtime_pm_debug_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv = s->private;
|
||||
struct cnss_pci_data *pci_priv;
|
||||
int i;
|
||||
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
pci_priv = plat_priv->bus_priv;
|
||||
if (!pci_priv)
|
||||
return -ENODEV;
|
||||
|
||||
seq_puts(s, "\nUsage: echo <action> > <debugfs_path>/cnss/runtime_pm\n");
|
||||
seq_puts(s, "<action> can be one of below:\n");
|
||||
seq_puts(s, "usage_count: get runtime PM usage count\n");
|
||||
seq_puts(s, "reques_resume: do async runtime PM resume\n");
|
||||
seq_puts(s, "resume: do sync runtime PM resume\n");
|
||||
seq_puts(s, "get: do runtime PM get\n");
|
||||
seq_puts(s, "get_noresume: do runtime PM get noresume\n");
|
||||
seq_puts(s, "put_noidle: do runtime PM put noidle\n");
|
||||
seq_puts(s, "put_autosuspend: do runtime PM put autosuspend\n");
|
||||
seq_puts(s, "mark_last_busy: do runtime PM mark last busy\n");
|
||||
seq_puts(s, "resume_bus: do bus resume only\n");
|
||||
seq_puts(s, "suspend_bus: do bus suspend only\n");
|
||||
|
||||
seq_puts(s, "\nStats:\n");
|
||||
seq_printf(s, "%s: %u\n", "get count",
|
||||
atomic_read(&pci_priv->pm_stats.runtime_get));
|
||||
seq_printf(s, "%s: %u\n", "put count",
|
||||
atomic_read(&pci_priv->pm_stats.runtime_put));
|
||||
seq_printf(s, "%-10s%-10s%-10s%-15s%-15s\n",
|
||||
"id:", "get", "put", "get time(us)", "put time(us)");
|
||||
for (i = 0; i < RTPM_ID_MAX; i++) {
|
||||
seq_printf(s, "%d%-9s", i, ":");
|
||||
seq_printf(s, "%-10d",
|
||||
atomic_read(&pci_priv->pm_stats.runtime_get_id[i]));
|
||||
seq_printf(s, "%-10d",
|
||||
atomic_read(&pci_priv->pm_stats.runtime_put_id[i]));
|
||||
seq_printf(s, "%-15llu",
|
||||
pci_priv->pm_stats.runtime_get_timestamp_id[i]);
|
||||
seq_printf(s, "%-15llu\n",
|
||||
pci_priv->pm_stats.runtime_put_timestamp_id[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_runtime_pm_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, cnss_runtime_pm_debug_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations cnss_runtime_pm_debug_fops = {
|
||||
.read = seq_read,
|
||||
.write = cnss_runtime_pm_debug_write,
|
||||
.open = cnss_runtime_pm_debug_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static ssize_t cnss_control_params_debug_write(struct file *fp,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *off)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv =
|
||||
((struct seq_file *)fp->private_data)->private;
|
||||
char buf[64];
|
||||
char *sptr, *token;
|
||||
char *cmd;
|
||||
u32 val;
|
||||
unsigned int len = 0;
|
||||
const char *delim = " ";
|
||||
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
sptr = buf;
|
||||
|
||||
token = strsep(&sptr, delim);
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
if (!sptr)
|
||||
return -EINVAL;
|
||||
cmd = token;
|
||||
|
||||
token = strsep(&sptr, delim);
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
if (kstrtou32(token, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (strcmp(cmd, "quirks") == 0)
|
||||
plat_priv->ctrl_params.quirks = val;
|
||||
else if (strcmp(cmd, "mhi_timeout") == 0)
|
||||
plat_priv->ctrl_params.mhi_timeout = val;
|
||||
else if (strcmp(cmd, "mhi_m2_timeout") == 0)
|
||||
plat_priv->ctrl_params.mhi_m2_timeout = val;
|
||||
else if (strcmp(cmd, "qmi_timeout") == 0)
|
||||
plat_priv->ctrl_params.qmi_timeout = val;
|
||||
else if (strcmp(cmd, "bdf_type") == 0)
|
||||
plat_priv->ctrl_params.bdf_type = val;
|
||||
else if (strcmp(cmd, "time_sync_period") == 0)
|
||||
plat_priv->ctrl_params.time_sync_period = val;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int cnss_show_quirks_state(struct seq_file *s,
|
||||
struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
enum cnss_debug_quirks i;
|
||||
int skip = 0;
|
||||
unsigned long state;
|
||||
|
||||
seq_printf(s, "quirks: 0x%lx (", plat_priv->ctrl_params.quirks);
|
||||
for (i = 0, state = plat_priv->ctrl_params.quirks;
|
||||
state != 0; state >>= 1, i++) {
|
||||
if (!(state & 0x1))
|
||||
continue;
|
||||
if (skip++)
|
||||
seq_puts(s, " | ");
|
||||
|
||||
switch (i) {
|
||||
case LINK_DOWN_SELF_RECOVERY:
|
||||
seq_puts(s, "LINK_DOWN_SELF_RECOVERY");
|
||||
continue;
|
||||
case SKIP_DEVICE_BOOT:
|
||||
seq_puts(s, "SKIP_DEVICE_BOOT");
|
||||
continue;
|
||||
case USE_CORE_ONLY_FW:
|
||||
seq_puts(s, "USE_CORE_ONLY_FW");
|
||||
continue;
|
||||
case SKIP_RECOVERY:
|
||||
seq_puts(s, "SKIP_RECOVERY");
|
||||
continue;
|
||||
case QMI_BYPASS:
|
||||
seq_puts(s, "QMI_BYPASS");
|
||||
continue;
|
||||
case ENABLE_WALTEST:
|
||||
seq_puts(s, "WALTEST");
|
||||
continue;
|
||||
case ENABLE_PCI_LINK_DOWN_PANIC:
|
||||
seq_puts(s, "PCI_LINK_DOWN_PANIC");
|
||||
continue;
|
||||
case FBC_BYPASS:
|
||||
seq_puts(s, "FBC_BYPASS");
|
||||
continue;
|
||||
case ENABLE_DAEMON_SUPPORT:
|
||||
seq_puts(s, "DAEMON_SUPPORT");
|
||||
continue;
|
||||
case DISABLE_DRV:
|
||||
seq_puts(s, "DISABLE_DRV");
|
||||
continue;
|
||||
case DISABLE_IO_COHERENCY:
|
||||
seq_puts(s, "DISABLE_IO_COHERENCY");
|
||||
continue;
|
||||
case IGNORE_PCI_LINK_FAILURE:
|
||||
seq_puts(s, "IGNORE_PCI_LINK_FAILURE");
|
||||
continue;
|
||||
case DISABLE_TIME_SYNC:
|
||||
seq_puts(s, "DISABLE_TIME_SYNC");
|
||||
continue;
|
||||
}
|
||||
|
||||
seq_printf(s, "UNKNOWN-%d", i);
|
||||
}
|
||||
seq_puts(s, ")\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_control_params_debug_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct cnss_plat_data *cnss_priv = s->private;
|
||||
|
||||
seq_puts(s, "\nUsage: echo <params_name> <value> > <debugfs_path>/cnss/control_params\n");
|
||||
seq_puts(s, "<params_name> can be one of below:\n");
|
||||
seq_puts(s, "quirks: Debug quirks for driver\n");
|
||||
seq_puts(s, "mhi_timeout: Timeout for MHI operation in milliseconds\n");
|
||||
seq_puts(s, "qmi_timeout: Timeout for QMI message in milliseconds\n");
|
||||
seq_puts(s, "bdf_type: Type of board data file to be downloaded\n");
|
||||
seq_puts(s, "time_sync_period: Time period to do time sync with device in milliseconds\n");
|
||||
|
||||
seq_puts(s, "\nCurrent value:\n");
|
||||
cnss_show_quirks_state(s, cnss_priv);
|
||||
seq_printf(s, "mhi_timeout: %u\n", cnss_priv->ctrl_params.mhi_timeout);
|
||||
seq_printf(s, "mhi_m2_timeout: %u\n",
|
||||
cnss_priv->ctrl_params.mhi_m2_timeout);
|
||||
seq_printf(s, "qmi_timeout: %u\n", cnss_priv->ctrl_params.qmi_timeout);
|
||||
seq_printf(s, "bdf_type: %u\n", cnss_priv->ctrl_params.bdf_type);
|
||||
seq_printf(s, "time_sync_period: %u\n",
|
||||
cnss_priv->ctrl_params.time_sync_period);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_control_params_debug_open(struct inode *inode,
|
||||
struct file *file)
|
||||
{
|
||||
return single_open(file, cnss_control_params_debug_show,
|
||||
inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations cnss_control_params_debug_fops = {
|
||||
.read = seq_read,
|
||||
.write = cnss_control_params_debug_write,
|
||||
.open = cnss_control_params_debug_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static ssize_t cnss_dynamic_feature_write(struct file *fp,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *off)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv =
|
||||
((struct seq_file *)fp->private_data)->private;
|
||||
int ret = 0;
|
||||
u64 val;
|
||||
|
||||
ret = kstrtou64_from_user(user_buf, count, 0, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
plat_priv->dynamic_feature = val;
|
||||
ret = cnss_wlfw_dynamic_feature_mask_send_sync(plat_priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int cnss_dynamic_feature_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct cnss_plat_data *cnss_priv = s->private;
|
||||
|
||||
seq_printf(s, "dynamic_feature: 0x%llx\n", cnss_priv->dynamic_feature);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_dynamic_feature_open(struct inode *inode,
|
||||
struct file *file)
|
||||
{
|
||||
return single_open(file, cnss_dynamic_feature_show,
|
||||
inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations cnss_dynamic_feature_fops = {
|
||||
.read = seq_read,
|
||||
.write = cnss_dynamic_feature_write,
|
||||
.open = cnss_dynamic_feature_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
#ifdef CONFIG_CNSS2_DEBUG
|
||||
static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
struct dentry *root_dentry = plat_priv->root_dentry;
|
||||
|
||||
debugfs_create_file("dev_boot", 0600, root_dentry, plat_priv,
|
||||
&cnss_dev_boot_debug_fops);
|
||||
debugfs_create_file("reg_read", 0600, root_dentry, plat_priv,
|
||||
&cnss_reg_read_debug_fops);
|
||||
debugfs_create_file("reg_write", 0600, root_dentry, plat_priv,
|
||||
&cnss_reg_write_debug_fops);
|
||||
debugfs_create_file("runtime_pm", 0600, root_dentry, plat_priv,
|
||||
&cnss_runtime_pm_debug_fops);
|
||||
debugfs_create_file("control_params", 0600, root_dentry, plat_priv,
|
||||
&cnss_control_params_debug_fops);
|
||||
debugfs_create_file("dynamic_feature", 0600, root_dentry, plat_priv,
|
||||
&cnss_dynamic_feature_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int cnss_debugfs_create(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
int ret = 0;
|
||||
struct dentry *root_dentry;
|
||||
|
||||
root_dentry = debugfs_create_dir("cnss", 0);
|
||||
if (IS_ERR(root_dentry)) {
|
||||
ret = PTR_ERR(root_dentry);
|
||||
cnss_pr_err("Unable to create debugfs %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
plat_priv->root_dentry = root_dentry;
|
||||
|
||||
debugfs_create_file("pin_connect_result", 0644, root_dentry, plat_priv,
|
||||
&cnss_pin_connect_fops);
|
||||
debugfs_create_file("stats", 0644, root_dentry, plat_priv,
|
||||
&cnss_stats_fops);
|
||||
|
||||
cnss_create_debug_only_node(plat_priv);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cnss_debugfs_destroy(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
debugfs_remove_recursive(plat_priv->root_dentry);
|
||||
}
|
||||
#else
|
||||
int cnss_debugfs_create(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
plat_priv->root_dentry = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnss_debugfs_destroy(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPC_LOGGING)
|
||||
void cnss_debug_ipc_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: %pV", log_level, &vaf);
|
||||
|
||||
ipc_log_string(log_ctx, "[%s] %s: %pV", process, fn, &vaf);
|
||||
|
||||
va_end(va_args);
|
||||
}
|
||||
|
||||
static int cnss_ipc_logging_init(void)
|
||||
{
|
||||
cnss_ipc_log_context = ipc_log_context_create(CNSS_IPC_LOG_PAGES,
|
||||
"cnss", 0);
|
||||
if (!cnss_ipc_log_context) {
|
||||
cnss_pr_err("Unable to create IPC log context\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cnss_ipc_log_long_context = ipc_log_context_create(CNSS_IPC_LOG_PAGES,
|
||||
"cnss-long", 0);
|
||||
if (!cnss_ipc_log_long_context) {
|
||||
cnss_pr_err("Unable to create IPC long log context\n");
|
||||
ipc_log_context_destroy(cnss_ipc_log_context);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cnss_ipc_logging_deinit(void)
|
||||
{
|
||||
if (cnss_ipc_log_long_context) {
|
||||
ipc_log_context_destroy(cnss_ipc_log_long_context);
|
||||
cnss_ipc_log_long_context = NULL;
|
||||
}
|
||||
|
||||
if (cnss_ipc_log_context) {
|
||||
ipc_log_context_destroy(cnss_ipc_log_context);
|
||||
cnss_ipc_log_context = NULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static int cnss_ipc_logging_init(void) { return 0; }
|
||||
static void cnss_ipc_logging_deinit(void) {}
|
||||
void cnss_debug_ipc_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: %pV", log_level, &vaf);
|
||||
|
||||
va_end(va_args);
|
||||
}
|
||||
#endif
|
||||
|
||||
int cnss_debug_init(void)
|
||||
{
|
||||
return cnss_ipc_logging_init();
|
||||
}
|
||||
|
||||
void cnss_debug_deinit(void)
|
||||
{
|
||||
cnss_ipc_logging_deinit();
|
||||
}
|
87
cnss2/debug.h
Normal file
87
cnss2/debug.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef _CNSS_DEBUG_H
|
||||
#define _CNSS_DEBUG_H
|
||||
|
||||
#include <linux/printk.h>
|
||||
|
||||
#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;
|
||||
|
||||
#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__, \
|
||||
KERN_ERR, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#define cnss_pr_warn(_fmt, ...) \
|
||||
cnss_debug_log_print(proc_name, __func__, \
|
||||
KERN_WARNING, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#define cnss_pr_info(_fmt, ...) \
|
||||
cnss_debug_log_print(proc_name, __func__, \
|
||||
KERN_INFO, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#define cnss_pr_dbg(_fmt, ...) \
|
||||
cnss_debug_log_print(proc_name, __func__, \
|
||||
KERN_DEBUG, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#define cnss_pr_vdbg(_fmt, ...) \
|
||||
cnss_debug_log_long_print(proc_name, __func__, \
|
||||
KERN_DEBUG, _fmt, ##__VA_ARGS__)
|
||||
|
||||
#define cnss_pr_buf(_fmt, ...) \
|
||||
cnss_debug_log_long_print(proc_name, __func__, \
|
||||
NULL, _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,
|
||||
const char *log_level, char *fmt, ...);
|
||||
#endif /* _CNSS_DEBUG_H */
|
213
cnss2/genl.c
Normal file
213
cnss2/genl.c
Normal file
@@ -0,0 +1,213 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2019, The Linux Foundation. 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"
|
||||
|
||||
#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("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("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);
|
||||
}
|
17
cnss2/genl.h
Normal file
17
cnss2/genl.h
Normal file
@@ -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
|
450
cnss2/ip_multimedia_subsystem_private_service_v01.c
Normal file
450
cnss2/ip_multimedia_subsystem_private_service_v01.c
Normal file
@@ -0,0 +1,450 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2019-2020, The Linux Foundation. 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_for_indications_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,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info
|
||||
ims_private_service_subscribe_for_indications_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,
|
||||
},
|
||||
};
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
134
cnss2/ip_multimedia_subsystem_private_service_v01.h
Normal file
134
cnss2/ip_multimedia_subsystem_private_service_v01.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2020, The Linux Foundation. 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_for_indications_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_for_indications_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
|
3477
cnss2/main.c
Normal file
3477
cnss2/main.c
Normal file
File diff suppressed because it is too large
Load Diff
594
cnss2/main.h
Normal file
594
cnss2/main.h
Normal file
@@ -0,0 +1,594 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2016-2021, The Linux Foundation. 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/platform_device.h>
|
||||
#include <linux/time64.h>
|
||||
#include <net/cnss2.h>
|
||||
#if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2)
|
||||
#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 "qmi.h"
|
||||
|
||||
#define MAX_NO_OF_MAC_ADDR 4
|
||||
#define QMI_WLFW_MAX_TIMESTAMP_LEN 32
|
||||
#define QMI_WLFW_MAX_NUM_MEM_SEG 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_V2_NUMBER 2
|
||||
#define POWER_ON_RETRY_MAX_TIMES 3
|
||||
#define POWER_ON_RETRY_DELAY_MS 200
|
||||
|
||||
#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)
|
||||
|
||||
enum cnss_dev_bus_type {
|
||||
CNSS_BUS_NONE = -1,
|
||||
CNSS_BUS_PCI,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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 *wlan_en_active;
|
||||
struct pinctrl_state *wlan_en_sleep;
|
||||
int bt_en_gpio;
|
||||
int xo_clk_gpio; /*qca6490 only */
|
||||
};
|
||||
|
||||
#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,
|
||||
};
|
||||
|
||||
enum cnss_fw_dump_type {
|
||||
CNSS_FW_IMAGE,
|
||||
CNSS_FW_RDDM,
|
||||
CNSS_FW_REMOTE_HEAP,
|
||||
CNSS_FW_DUMP_TYPE_MAX,
|
||||
};
|
||||
|
||||
struct cnss_dump_entry {
|
||||
u32 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];
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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_plat_data {
|
||||
struct platform_device *plat_dev;
|
||||
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;
|
||||
#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 hds_enabled;
|
||||
unsigned long driver_state;
|
||||
struct list_head event_list;
|
||||
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];
|
||||
struct cnss_fw_mem m3_mem;
|
||||
struct cnss_fw_mem *cal_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];
|
||||
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 */
|
||||
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];
|
||||
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);
|
||||
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;
|
||||
u8 pcie_gen_speed;
|
||||
struct cnss_dms_data dms;
|
||||
int power_up_error;
|
||||
u32 hw_trc_override;
|
||||
struct mbox_client mbox_client_data;
|
||||
struct mbox_chan *mbox_chan;
|
||||
const char *vreg_ol_cpr, *vreg_ipa;
|
||||
bool adsp_pc_enabled;
|
||||
u64 feature_list;
|
||||
};
|
||||
|
||||
#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
|
||||
|
||||
struct cnss_plat_data *cnss_get_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);
|
||||
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_power_on_device(struct cnss_plat_data *plat_priv);
|
||||
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_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);
|
||||
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_mbox_init(struct cnss_plat_data *plat_priv);
|
||||
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_get_feature_list(struct cnss_plat_data *plat_priv,
|
||||
u64 *feature_list);
|
||||
#endif /* _CNSS_MAIN_H */
|
6190
cnss2/pci.c
Normal file
6190
cnss2/pci.c
Normal file
File diff suppressed because it is too large
Load Diff
263
cnss2/pci.h
Normal file
263
cnss2/pci.h
Normal file
@@ -0,0 +1,263 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef _CNSS_PCI_H
|
||||
#define _CNSS_PCI_H
|
||||
|
||||
#include <linux/iommu.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/pci.h>
|
||||
|
||||
#include "main.h"
|
||||
|
||||
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_WCN7850,
|
||||
};
|
||||
|
||||
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_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;
|
||||
struct mhi_controller *mhi_ctrl;
|
||||
unsigned long mhi_state;
|
||||
u32 remap_window;
|
||||
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;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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_m3(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);
|
||||
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_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);
|
||||
|
||||
#endif /* _CNSS_PCI_H */
|
1283
cnss2/power.c
Normal file
1283
cnss2/power.c
Normal file
File diff suppressed because it is too large
Load Diff
3448
cnss2/qmi.c
Normal file
3448
cnss2/qmi.c
Normal file
File diff suppressed because it is too large
Load Diff
316
cnss2/qmi.h
Normal file
316
cnss2/qmi.h
Normal file
@@ -0,0 +1,316 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2015-2021, The Linux Foundation. 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_m3_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 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);
|
||||
#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_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
#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 */
|
338
cnss2/reg.h
Normal file
338
cnss2/reg.h
Normal file
@@ -0,0 +1,338 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef _CNSS_REG_H
|
||||
#define _CNSS_REG_H
|
||||
|
||||
#define QCA6390_PCIE_REMAP_BAR_CTRL_OFFSET 0x310C
|
||||
|
||||
#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 PCIE_SHADOW_REG_VALUE_0 0x8FC
|
||||
#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 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_V2_SBL_DATA_START 0x016C8580
|
||||
#define QCA6390_V2_SBL_DATA_END (0x016C8580 + 0x00011000)
|
||||
#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_V1_SBL_DATA_START 0x0143B000
|
||||
#define QCA6490_V1_SBL_DATA_END (0x0143B000 + 0x00011000)
|
||||
#define QCA6490_V2_SBL_DATA_START 0x01435000
|
||||
#define QCA6490_V2_SBL_DATA_END (0x01435000 + 0x00011000)
|
||||
#define QCA6490_DEBUG_SBL_LOG_SRAM_MAX_SIZE 48
|
||||
|
||||
#define WCN7850_DEBUG_PBL_LOG_SRAM_START 0x01403D98
|
||||
#define WCN7850_DEBUG_PBL_LOG_SRAM_MAX_SIZE 40
|
||||
#define WCN7850_SBL_DATA_START 0x01790000
|
||||
#define WCN7850_SBL_DATA_END (0x01790000 + 0x00011000)
|
||||
#define WCN7850_DEBUG_SBL_LOG_SRAM_MAX_SIZE 48
|
||||
#define WCN7850_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 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 QCA6390_PCIE_PCIE_WCSS_STATUS_FOR_DEBUG_LOW_PCIE_LOCAL_REG 0x01E03140
|
||||
#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 0x1E05090
|
||||
#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 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_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
|
||||
#endif
|
9
cnss_genl/Kconfig
Normal file
9
cnss_genl/Kconfig
Normal file
@@ -0,0 +1,9 @@
|
||||
# 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.
|
3
cnss_genl/Makefile
Normal file
3
cnss_genl/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_CNSS_GENL) := cnss_nl.o
|
229
cnss_genl/cnss_nl.c
Normal file
229
cnss_genl/cnss_nl.c
Normal file
@@ -0,0 +1,229 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#include <net/genetlink.h>
|
||||
#include <net/cnss_nl.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.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 },
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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");
|
9
cnss_prealloc/Kconfig
Normal file
9
cnss_prealloc/Kconfig
Normal file
@@ -0,0 +1,9 @@
|
||||
# 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.
|
3
cnss_prealloc/Makefile
Normal file
3
cnss_prealloc/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += cnss_prealloc.o
|
294
cnss_prealloc/cnss_prealloc.c
Normal file
294
cnss_prealloc/cnss_prealloc.c
Normal file
@@ -0,0 +1,294 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2012,2014-2017,2019-2021 The Linux Foundation. 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 <net/cnss_prealloc.h>
|
||||
|
||||
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[] = {
|
||||
{8 * 1024, 22, "cnss-pool-8k", NULL, NULL},
|
||||
{16 * 1024, 16, "cnss-pool-16k", NULL, NULL},
|
||||
{32 * 1024, 6, "cnss-pool-32k", NULL, NULL},
|
||||
{64 * 1024, 8, "cnss-pool-64k", NULL, NULL},
|
||||
{128 * 1024, 2, "cnss-pool-128k", NULL, NULL},
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 < ARRAY_SIZE(cnss_pools); 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;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cnss_pools); 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_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.
|
||||
*
|
||||
*/
|
||||
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 < ARRAY_SIZE(cnss_pools); i++) {
|
||||
if (cnss_pools[i].cache == cache)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (in_interrupt() || irqs_disabled())
|
||||
gfp_mask |= GFP_ATOMIC;
|
||||
else
|
||||
gfp_mask |= GFP_KERNEL;
|
||||
|
||||
if (size >= cnss_pool_alloc_threshold()) {
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cnss_pools); i++) {
|
||||
if (cnss_pools[i].size >= size) {
|
||||
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)
|
||||
return 0;
|
||||
|
||||
i = cnss_pool_get_index(mem);
|
||||
|
||||
if (i >= 0 && i < ARRAY_SIZE(cnss_pools)) {
|
||||
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 cnss_pool_init();
|
||||
}
|
||||
|
||||
static void __exit cnss_prealloc_exit(void)
|
||||
{
|
||||
cnss_pool_deinit();
|
||||
}
|
||||
|
||||
module_init(cnss_prealloc_init);
|
||||
module_exit(cnss_prealloc_exit);
|
||||
|
20
cnss_utils/Kconfig
Normal file
20
cnss_utils/Kconfig
Normal file
@@ -0,0 +1,20 @@
|
||||
# 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.
|
8
cnss_utils/Makefile
Normal file
8
cnss_utils/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
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
|
||||
|
||||
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
|
975
cnss_utils/cnss_plat_ipc_qmi.c
Normal file
975
cnss_utils/cnss_plat_ipc_qmi.c
Normal file
@@ -0,0 +1,975 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2021, The Linux Foundation. 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
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
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) {};
|
||||
|
||||
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;
|
||||
|
||||
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 =
|
||||
CNSS_PLAT_IPC_QMI_REG_CLIENT_REQ_MSG_V01_MAX_MSG_LEN,
|
||||
.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 =
|
||||
CNSS_PLAT_IPC_QMI_INIT_SETUP_REQ_MSG_V01_MAX_MSG_LEN,
|
||||
.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 =
|
||||
CNSS_PLAT_IPC_QMI_FILE_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN,
|
||||
.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 =
|
||||
CNSS_PLAT_IPC_QMI_FILE_UPLOAD_REQ_MSG_V01_MAX_MSG_LEN,
|
||||
.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)
|
||||
{
|
||||
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;
|
||||
|
||||
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",
|
||||
ret, QMI_INIT_RETRY_DELAY_MS,
|
||||
QMI_INIT_RETRY_MAX_TIMES);
|
||||
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");
|
86
cnss_utils/cnss_plat_ipc_qmi.h
Normal file
86
cnss_utils/cnss_plat_ipc_qmi.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2020-2021, The Linux Foundation. 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
|
||||
* @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 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
|
402
cnss_utils/cnss_plat_ipc_service_v01.c
Normal file
402
cnss_utils/cnss_plat_ipc_service_v01.c
Normal file
@@ -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");
|
127
cnss_utils/cnss_plat_ipc_service_v01.h
Normal file
127
cnss_utils/cnss_plat_ipc_service_v01.h
Normal file
@@ -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
|
500
cnss_utils/cnss_utils.c
Normal file
500
cnss_utils/cnss_utils.c
Normal file
@@ -0,0 +1,500 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2017, 2019, 2021 The Linux Foundation. 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>
|
||||
#include <net/cnss_utils.h>
|
||||
|
||||
#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;
|
||||
} *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);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
mutex_init(&priv->unsafe_channel_list_lock);
|
||||
spin_lock_init(&priv->dfs_nol_info_lock);
|
||||
cnss_utils_debugfs_create(priv);
|
||||
cnss_utils_priv = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit cnss_utils_exit(void)
|
||||
{
|
||||
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");
|
75
cnss_utils/device_management_service_v01.c
Normal file
75
cnss_utils/device_management_service_v01.c
Normal file
@@ -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);
|
38
cnss_utils/device_management_service_v01.h
Normal file
38
cnss_utils/device_management_service_v01.h
Normal file
@@ -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
|
5495
cnss_utils/wlan_firmware_service_v01.c
Normal file
5495
cnss_utils/wlan_firmware_service_v01.c
Normal file
File diff suppressed because it is too large
Load Diff
1271
cnss_utils/wlan_firmware_service_v01.h
Normal file
1271
cnss_utils/wlan_firmware_service_v01.h
Normal file
File diff suppressed because it is too large
Load Diff
278
inc/cnss2.h
Normal file
278
inc/cnss2.h
Normal file
@@ -0,0 +1,278 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef _NET_CNSS2_H
|
||||
#define _NET_CNSS2_H
|
||||
|
||||
#include <linux/pci.h>
|
||||
|
||||
#define CNSS_MAX_FILE_NAME 20
|
||||
#define CNSS_MAX_TIMESTAMP_LEN 32
|
||||
#define CNSS_MAX_DEV_MEM_NUM 4
|
||||
|
||||
/*
|
||||
* Temporary change for compilation, will be removed
|
||||
* after WLAN host driver switched to use new APIs
|
||||
*/
|
||||
#define CNSS_API_WITH_DEV
|
||||
|
||||
enum cnss_bus_width_type {
|
||||
CNSS_BUS_WIDTH_NONE,
|
||||
CNSS_BUS_WIDTH_IDLE,
|
||||
CNSS_BUS_WIDTH_LOW,
|
||||
CNSS_BUS_WIDTH_MEDIUM,
|
||||
CNSS_BUS_WIDTH_HIGH,
|
||||
CNSS_BUS_WIDTH_VERY_HIGH,
|
||||
CNSS_BUS_WIDTH_LOW_LATENCY
|
||||
};
|
||||
|
||||
enum cnss_platform_cap_flag {
|
||||
CNSS_HAS_EXTERNAL_SWREG = 0x01,
|
||||
CNSS_HAS_UART_ACCESS = 0x02,
|
||||
CNSS_HAS_DRV_SUPPORT = 0x04,
|
||||
};
|
||||
|
||||
struct cnss_platform_cap {
|
||||
u32 cap_flag;
|
||||
};
|
||||
|
||||
struct cnss_fw_files {
|
||||
char image_file[CNSS_MAX_FILE_NAME];
|
||||
char board_data[CNSS_MAX_FILE_NAME];
|
||||
char otp_data[CNSS_MAX_FILE_NAME];
|
||||
char utf_file[CNSS_MAX_FILE_NAME];
|
||||
char utf_board_data[CNSS_MAX_FILE_NAME];
|
||||
char epping_file[CNSS_MAX_FILE_NAME];
|
||||
char evicted_data[CNSS_MAX_FILE_NAME];
|
||||
};
|
||||
|
||||
struct cnss_device_version {
|
||||
u32 family_number;
|
||||
u32 device_number;
|
||||
u32 major_version;
|
||||
u32 minor_version;
|
||||
};
|
||||
|
||||
struct cnss_dev_mem_info {
|
||||
u64 start;
|
||||
u64 size;
|
||||
};
|
||||
|
||||
struct cnss_soc_info {
|
||||
void __iomem *va;
|
||||
phys_addr_t pa;
|
||||
uint32_t chip_id;
|
||||
uint32_t chip_family;
|
||||
uint32_t board_id;
|
||||
uint32_t soc_id;
|
||||
uint32_t fw_version;
|
||||
char fw_build_timestamp[CNSS_MAX_TIMESTAMP_LEN + 1];
|
||||
struct cnss_device_version device_version;
|
||||
struct cnss_dev_mem_info dev_mem_info[CNSS_MAX_DEV_MEM_NUM];
|
||||
};
|
||||
|
||||
struct cnss_wlan_runtime_ops {
|
||||
int (*runtime_suspend)(struct pci_dev *pdev);
|
||||
int (*runtime_resume)(struct pci_dev *pdev);
|
||||
};
|
||||
|
||||
enum cnss_driver_status {
|
||||
CNSS_UNINITIALIZED,
|
||||
CNSS_INITIALIZED,
|
||||
CNSS_LOAD_UNLOAD,
|
||||
CNSS_RECOVERY,
|
||||
CNSS_FW_DOWN,
|
||||
CNSS_HANG_EVENT,
|
||||
CNSS_BUS_EVENT,
|
||||
};
|
||||
|
||||
enum cnss_bus_event_type {
|
||||
BUS_EVENT_PCI_LINK_DOWN = 0,
|
||||
|
||||
BUS_EVENT_INVALID = 0xFFFF,
|
||||
};
|
||||
|
||||
struct cnss_hang_event {
|
||||
void *hang_event_data;
|
||||
u16 hang_event_data_len;
|
||||
};
|
||||
|
||||
struct cnss_bus_event {
|
||||
enum cnss_bus_event_type etype;
|
||||
void *event_data;
|
||||
};
|
||||
|
||||
struct cnss_uevent_data {
|
||||
enum cnss_driver_status status;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct cnss_wlan_driver {
|
||||
char *name;
|
||||
int (*probe)(struct pci_dev *pdev, const struct pci_device_id *id);
|
||||
void (*remove)(struct pci_dev *pdev);
|
||||
int (*idle_restart)(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id);
|
||||
int (*idle_shutdown)(struct pci_dev *pdev);
|
||||
int (*reinit)(struct pci_dev *pdev, const struct pci_device_id *id);
|
||||
void (*shutdown)(struct pci_dev *pdev);
|
||||
void (*crash_shutdown)(struct pci_dev *pdev);
|
||||
int (*suspend)(struct pci_dev *pdev, pm_message_t state);
|
||||
int (*resume)(struct pci_dev *pdev);
|
||||
int (*suspend_noirq)(struct pci_dev *pdev);
|
||||
int (*resume_noirq)(struct pci_dev *pdev);
|
||||
void (*modem_status)(struct pci_dev *pdev, int state);
|
||||
void (*update_status)(struct pci_dev *pdev, uint32_t status);
|
||||
int (*update_event)(struct pci_dev *pdev,
|
||||
struct cnss_uevent_data *uevent);
|
||||
struct cnss_wlan_runtime_ops *runtime_ops;
|
||||
const struct pci_device_id *id_table;
|
||||
};
|
||||
|
||||
struct cnss_ce_tgt_pipe_cfg {
|
||||
u32 pipe_num;
|
||||
u32 pipe_dir;
|
||||
u32 nentries;
|
||||
u32 nbytes_max;
|
||||
u32 flags;
|
||||
u32 reserved;
|
||||
};
|
||||
|
||||
struct cnss_ce_svc_pipe_cfg {
|
||||
u32 service_id;
|
||||
u32 pipe_dir;
|
||||
u32 pipe_num;
|
||||
};
|
||||
|
||||
struct cnss_shadow_reg_cfg {
|
||||
u16 ce_id;
|
||||
u16 reg_offset;
|
||||
};
|
||||
|
||||
struct cnss_shadow_reg_v2_cfg {
|
||||
u32 addr;
|
||||
};
|
||||
|
||||
struct cnss_rri_over_ddr_cfg {
|
||||
u32 base_addr_low;
|
||||
u32 base_addr_high;
|
||||
};
|
||||
|
||||
struct cnss_wlan_enable_cfg {
|
||||
u32 num_ce_tgt_cfg;
|
||||
struct cnss_ce_tgt_pipe_cfg *ce_tgt_cfg;
|
||||
u32 num_ce_svc_pipe_cfg;
|
||||
struct cnss_ce_svc_pipe_cfg *ce_svc_cfg;
|
||||
u32 num_shadow_reg_cfg;
|
||||
struct cnss_shadow_reg_cfg *shadow_reg_cfg;
|
||||
u32 num_shadow_reg_v2_cfg;
|
||||
struct cnss_shadow_reg_v2_cfg *shadow_reg_v2_cfg;
|
||||
bool rri_over_ddr_cfg_valid;
|
||||
struct cnss_rri_over_ddr_cfg rri_over_ddr_cfg;
|
||||
};
|
||||
|
||||
enum cnss_driver_mode {
|
||||
CNSS_MISSION,
|
||||
CNSS_FTM,
|
||||
CNSS_EPPING,
|
||||
CNSS_WALTEST,
|
||||
CNSS_OFF,
|
||||
CNSS_CCPM,
|
||||
CNSS_QVIT,
|
||||
CNSS_CALIBRATION,
|
||||
};
|
||||
|
||||
enum cnss_recovery_reason {
|
||||
CNSS_REASON_DEFAULT,
|
||||
CNSS_REASON_LINK_DOWN,
|
||||
CNSS_REASON_RDDM,
|
||||
CNSS_REASON_TIMEOUT,
|
||||
};
|
||||
|
||||
enum cnss_remote_mem_type {
|
||||
CNSS_REMOTE_MEM_TYPE_FW,
|
||||
CNSS_REMOTE_MEM_TYPE_QDSS,
|
||||
CNSS_REMOTE_MEM_TYPE_MAX,
|
||||
};
|
||||
|
||||
struct cnss_mem_segment {
|
||||
size_t size;
|
||||
void *va;
|
||||
phys_addr_t pa;
|
||||
};
|
||||
|
||||
extern int cnss_wlan_register_driver(struct cnss_wlan_driver *driver);
|
||||
extern void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver);
|
||||
extern void cnss_device_crashed(struct device *dev);
|
||||
extern int cnss_pci_prevent_l1(struct device *dev);
|
||||
extern void cnss_pci_allow_l1(struct device *dev);
|
||||
extern int cnss_pci_link_down(struct device *dev);
|
||||
extern int cnss_pci_is_device_down(struct device *dev);
|
||||
extern void cnss_schedule_recovery(struct device *dev,
|
||||
enum cnss_recovery_reason reason);
|
||||
extern int cnss_self_recovery(struct device *dev,
|
||||
enum cnss_recovery_reason reason);
|
||||
extern int cnss_force_fw_assert(struct device *dev);
|
||||
extern int cnss_force_collect_rddm(struct device *dev);
|
||||
extern int cnss_qmi_send_get(struct device *dev);
|
||||
extern int cnss_qmi_send_put(struct device *dev);
|
||||
extern int cnss_qmi_send(struct device *dev, int type, void *cmd,
|
||||
int cmd_len, void *cb_ctx,
|
||||
int (*cb)(void *ctx, void *event, int event_len));
|
||||
extern void *cnss_get_virt_ramdump_mem(struct device *dev, unsigned long *size);
|
||||
extern int cnss_get_fw_files_for_target(struct device *dev,
|
||||
struct cnss_fw_files *pfw_files,
|
||||
u32 target_type, u32 target_version);
|
||||
extern int cnss_get_platform_cap(struct device *dev,
|
||||
struct cnss_platform_cap *cap);
|
||||
extern struct iommu_domain *cnss_smmu_get_domain(struct device *dev);
|
||||
extern int cnss_smmu_map(struct device *dev,
|
||||
phys_addr_t paddr, uint32_t *iova_addr, size_t size);
|
||||
extern int cnss_smmu_unmap(struct device *dev, uint32_t iova_addr, size_t size);
|
||||
extern int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info);
|
||||
extern int cnss_request_bus_bandwidth(struct device *dev, int bandwidth);
|
||||
extern int cnss_power_up(struct device *dev);
|
||||
extern int cnss_power_down(struct device *dev);
|
||||
extern int cnss_idle_restart(struct device *dev);
|
||||
extern int cnss_idle_shutdown(struct device *dev);
|
||||
extern void cnss_request_pm_qos(struct device *dev, u32 qos_val);
|
||||
extern void cnss_remove_pm_qos(struct device *dev);
|
||||
extern void cnss_lock_pm_sem(struct device *dev);
|
||||
extern void cnss_release_pm_sem(struct device *dev);
|
||||
extern void cnss_pci_lock_reg_window(struct device *dev, unsigned long *flags);
|
||||
extern void cnss_pci_unlock_reg_window(struct device *dev,
|
||||
unsigned long *flags);
|
||||
extern int cnss_wlan_pm_control(struct device *dev, bool vote);
|
||||
extern int cnss_auto_suspend(struct device *dev);
|
||||
extern int cnss_auto_resume(struct device *dev);
|
||||
extern int cnss_pci_is_drv_connected(struct device *dev);
|
||||
extern int cnss_pci_force_wake_request_sync(struct device *dev, int timeout);
|
||||
extern int cnss_pci_force_wake_request(struct device *dev);
|
||||
extern int cnss_pci_is_device_awake(struct device *dev);
|
||||
extern int cnss_pci_force_wake_release(struct device *dev);
|
||||
extern int cnss_get_user_msi_assignment(struct device *dev, char *user_name,
|
||||
int *num_vectors,
|
||||
uint32_t *user_base_data,
|
||||
uint32_t *base_vector);
|
||||
extern int cnss_get_msi_irq(struct device *dev, unsigned int vector);
|
||||
extern void cnss_get_msi_address(struct device *dev, uint32_t *msi_addr_low,
|
||||
uint32_t *msi_addr_high);
|
||||
extern int cnss_wlan_enable(struct device *dev,
|
||||
struct cnss_wlan_enable_cfg *config,
|
||||
enum cnss_driver_mode mode,
|
||||
const char *host_version);
|
||||
extern int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode);
|
||||
extern unsigned int cnss_get_boot_timeout(struct device *dev);
|
||||
extern int cnss_athdiag_read(struct device *dev, uint32_t offset,
|
||||
uint32_t mem_type, uint32_t data_len,
|
||||
uint8_t *output);
|
||||
extern int cnss_athdiag_write(struct device *dev, uint32_t offset,
|
||||
uint32_t mem_type, uint32_t data_len,
|
||||
uint8_t *input);
|
||||
extern int cnss_set_fw_log_mode(struct device *dev, uint8_t fw_log_mode);
|
||||
extern int cnss_set_pcie_gen_speed(struct device *dev, u8 pcie_gen_speed);
|
||||
extern int cnss_get_mem_seg_count(enum cnss_remote_mem_type type, u32 *seg);
|
||||
extern int cnss_get_mem_segment_info(enum cnss_remote_mem_type type,
|
||||
struct cnss_mem_segment segment[],
|
||||
u32 segment_count);
|
||||
#endif /* _NET_CNSS2_H */
|
103
inc/cnss_nl.h
Normal file
103
inc/cnss_nl.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef _NET_CNSS_GENETLINK_H_
|
||||
#define _NET_CNSS_GENETLINK_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define CLD80211_MAX_COMMANDS 40
|
||||
#define CLD80211_MAX_NL_DATA 4096
|
||||
|
||||
/**
|
||||
* enum cld80211_attr - Driver/Application embeds the data in nlmsg with the
|
||||
* help of below attributes
|
||||
*
|
||||
* @CLD80211_ATTR_VENDOR_DATA: Embed all other attributes in this nested
|
||||
* attribute.
|
||||
* @CLD80211_ATTR_DATA: Embed complete data in this attribute
|
||||
* @CLD80211_ATTR_META_DATA: Embed meta data for above data. This will help
|
||||
* wlan driver to peek into request message packet without opening up definition
|
||||
* of complete request message.
|
||||
* @CLD80211_ATTR_CMD: cld80211 vendor subcommand in this attribute
|
||||
* @CLD80211_ATTR_CMD_TAG_DATA: cld80211 vendor subcommand data is present in
|
||||
* this attribute. It is a nested attribute with sub attributes of specified
|
||||
* vendor sub command.
|
||||
*
|
||||
* Any new message in future can be added as another attribute
|
||||
*/
|
||||
enum cld80211_attr {
|
||||
CLD80211_ATTR_VENDOR_DATA = 1,
|
||||
CLD80211_ATTR_DATA,
|
||||
CLD80211_ATTR_META_DATA,
|
||||
CLD80211_ATTR_CMD,
|
||||
CLD80211_ATTR_CMD_TAG_DATA,
|
||||
/* add new attributes above here */
|
||||
|
||||
__CLD80211_ATTR_AFTER_LAST,
|
||||
CLD80211_ATTR_MAX = __CLD80211_ATTR_AFTER_LAST - 1
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cld80211_multicast_groups - List of multicast groups supported
|
||||
*
|
||||
* @CLD80211_MCGRP_SVC_MSGS: WLAN service message will be sent to this group.
|
||||
* Ex: Status ind messages
|
||||
* @CLD80211_MCGRP_HOST_LOGS: All logging related messages from driver will be
|
||||
* sent to this multicast group
|
||||
* @CLD80211_MCGRP_FW_LOGS: Firmware logging messages will be sent to this group
|
||||
* @CLD80211_MCGRP_PER_PKT_STATS: Messages related packet stats debugging infra
|
||||
* will be sent to this group
|
||||
* @CLD80211_MCGRP_DIAG_EVENTS: Driver/Firmware status logging diag events will
|
||||
* be sent to this group
|
||||
* @CLD80211_MCGRP_FATAL_EVENTS: Any fatal message generated in driver/firmware
|
||||
* will be sent to this group
|
||||
* @CLD80211_MCGRP_OEM_MSGS: All OEM message will be sent to this group
|
||||
* Ex: LOWI messages
|
||||
*/
|
||||
enum cld80211_multicast_groups {
|
||||
CLD80211_MCGRP_SVC_MSGS,
|
||||
CLD80211_MCGRP_HOST_LOGS,
|
||||
CLD80211_MCGRP_FW_LOGS,
|
||||
CLD80211_MCGRP_PER_PKT_STATS,
|
||||
CLD80211_MCGRP_DIAG_EVENTS,
|
||||
CLD80211_MCGRP_FATAL_EVENTS,
|
||||
CLD80211_MCGRP_OEM_MSGS,
|
||||
};
|
||||
|
||||
/**
|
||||
* typedef cld80211_cb - Callback to be called when an nlmsg is received with
|
||||
* the registered cmd_id command from userspace
|
||||
* @data: Payload of the message to be sent to driver
|
||||
* @data_len: Length of the payload
|
||||
* @cb_ctx: callback context to be returned to driver when the callback
|
||||
* is called
|
||||
* @pid: process id of the sender
|
||||
*/
|
||||
typedef void (*cld80211_cb)(const void *data, int data_len,
|
||||
void *cb_ctx, int pid);
|
||||
|
||||
/**
|
||||
* register_cld_cmd_cb() - Allows cld driver to register for commands with
|
||||
* callback
|
||||
* @cmd_id: Command to be registered. Valid range [1, CLD80211_MAX_COMMANDS]
|
||||
* @cb: Callback to be called when an nlmsg is received with cmd_id command
|
||||
* from userspace
|
||||
* @cb_ctx: context provided by driver; Send this as cb_ctx of func()
|
||||
* to driver
|
||||
*/
|
||||
int register_cld_cmd_cb(u8 cmd_id, cld80211_cb cb, void *cb_ctx);
|
||||
|
||||
/**
|
||||
* deregister_cld_cmd_cb() - Allows cld driver to de-register the command it
|
||||
* has already registered
|
||||
* @cmd_id: Command to be deregistered.
|
||||
*/
|
||||
int deregister_cld_cmd_cb(u8 cmd_id);
|
||||
|
||||
/**
|
||||
* cld80211_get_genl_family() - Returns current netlink family context
|
||||
*/
|
||||
struct genl_family *cld80211_get_genl_family(void);
|
||||
|
||||
#endif /* _NET_CNSS_GENETLINK_H_ */
|
16
inc/cnss_prealloc.h
Normal file
16
inc/cnss_prealloc.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2015-2016,2019 The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef _NET_CNSS_PREALLOC_H_
|
||||
#define _NET_CNSS_PREALLOC_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define WCNSS_PRE_ALLOC_GET_THRESHOLD (4*1024)
|
||||
|
||||
extern void *wcnss_prealloc_get(size_t size);
|
||||
extern int wcnss_prealloc_put(void *ptr);
|
||||
extern int wcnss_pre_alloc_reset(void);
|
||||
void wcnss_prealloc_check_memory_leak(void);
|
||||
|
||||
#endif /* _NET_CNSS__PREALLOC_H_ */
|
38
inc/cnss_utils.h
Normal file
38
inc/cnss_utils.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2017, 2019 The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef _CNSS_UTILS_H_
|
||||
#define _CNSS_UTILS_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct device;
|
||||
|
||||
enum cnss_utils_cc_src {
|
||||
CNSS_UTILS_SOURCE_CORE,
|
||||
CNSS_UTILS_SOURCE_11D,
|
||||
CNSS_UTILS_SOURCE_USER
|
||||
};
|
||||
|
||||
extern int cnss_utils_set_wlan_unsafe_channel(struct device *dev,
|
||||
u16 *unsafe_ch_list,
|
||||
u16 ch_count);
|
||||
extern int cnss_utils_get_wlan_unsafe_channel(struct device *dev,
|
||||
u16 *unsafe_ch_list,
|
||||
u16 *ch_count, u16 buf_len);
|
||||
extern int cnss_utils_wlan_set_dfs_nol(struct device *dev,
|
||||
const void *info, u16 info_len);
|
||||
extern int cnss_utils_wlan_get_dfs_nol(struct device *dev,
|
||||
void *info, u16 info_len);
|
||||
extern int cnss_utils_get_driver_load_cnt(struct device *dev);
|
||||
extern void cnss_utils_increment_driver_load_cnt(struct device *dev);
|
||||
extern int cnss_utils_set_wlan_mac_address(const u8 *in, uint32_t len);
|
||||
extern u8 *cnss_utils_get_wlan_mac_address(struct device *dev, uint32_t *num);
|
||||
extern int cnss_utils_set_wlan_derived_mac_address(const u8 *in, uint32_t len);
|
||||
extern u8 *cnss_utils_get_wlan_derived_mac_address(struct device *dev,
|
||||
uint32_t *num);
|
||||
extern void cnss_utils_set_cc_source(struct device *dev,
|
||||
enum cnss_utils_cc_src cc_source);
|
||||
extern enum cnss_utils_cc_src cnss_utils_get_cc_source(struct device *dev);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user