net: cnss: add snapshot of cnss platform driver

This is a snapshot of the CNSS driver and associated files as of
msm-4.14 commit b56fde2f9abd44
("cnss: Add cnss driver to msm-4.14").

Add Kconfig dependency.
Comment obsolete codes to fix some compiler issues.

Change-Id: I89bf0a85b086c7482609b331273d9eaf2fb66648
Signed-off-by: Paul Zhang <paulz@codeaurora.org>
This commit is contained in:
Paul Zhang 2020-12-18 17:13:51 +08:00 • committed by Gerrit - the friendly Code Review server
commit bb06fdbcd0
21 changed files with 7600 additions and 5 deletions

View file

@ -9,7 +9,7 @@ menuconfig WLAN
depends on NET
select WIRELESS
default y
---help---
help
This section contains all the pre 802.11 and 802.11 wireless
device drivers. For a complete list of drivers and documentation
on them refer to the wireless wiki:
@ -54,7 +54,7 @@ config PCMCIA_RAYCS
select WIRELESS_EXT
select WEXT_SPY
select WEXT_PRIV
---help---
help
Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
(PC-card) wireless Ethernet networking card to your computer.
Please read the file <file:Documentation/networking/ray_cs.txt> for
@ -76,7 +76,7 @@ config PCMCIA_WL3501
config MAC80211_HWSIM
tristate "Simulated radio testing tool for mac80211"
depends on MAC80211
---help---
help
This driver is a developer testing tool that can be used to test
IEEE 802.11 networking stack (mac80211) functionality. This is not
needed for normal wireless LAN usage and is only for testing. See
@ -94,7 +94,7 @@ config USB_NET_RNDIS_WLAN
select USB_USBNET
select USB_NET_CDCETHER
select USB_NET_RNDIS_HOST
---help---
help
This is a driver for wireless RNDIS devices.
These are USB based adapters found in devices such as:
@ -118,7 +118,7 @@ config USB_NET_RNDIS_WLAN
config VIRT_WIFI
tristate "Wifi wrapper for ethernet drivers"
depends on CFG80211
---help---
help
This option adds support for ethernet connections to appear as if they
are wifi connections through a special rtnetlink device.
@ -135,7 +135,16 @@ config CLD_LL_CORE
Select Y to compile the driver in order to have WLAN functionality
support.
config CNSS_CRYPTO
tristate "Enable CNSS crypto support"
help
Add crypto support for the WLAN driver module.
This feature enable wlan driver to use the crypto APIs exported
from cnss platform driver. This crypto APIs used to generate cipher
key and add support for the WLAN driver module security protocol.
source "drivers/net/wireless/cnss2/Kconfig"
source "drivers/net/wireless/cnss/Kconfig"
source "drivers/net/wireless/cnss_utils/Kconfig"
source "drivers/net/wireless/cnss_genl/Kconfig"
source "drivers/net/wireless/cnss_prealloc/Kconfig"

View file

@ -31,6 +31,8 @@ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
obj-$(CONFIG_VIRT_WIFI) += virt_wifi.o
obj-$(CONFIG_CNSS2) += cnss2/
obj-$(CONFIG_CNSS) += cnss/
obj-$(CONFIG_CNSS_UTILS) += cnss_utils/
obj-$(CONFIG_CNSS_GENL) += cnss_genl/
obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += cnss_prealloc/
obj-$(CONFIG_CNSS_CRYPTO) += cnss_crypto/

View file

@ -0,0 +1,134 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# cnss device configuration
#
config CNSS
tristate "CNSS driver for wifi module"
select CNSS_UTILS
select CRYPTO
select CRYPTO_HASH
select CRYPTO_BLKCIPHER
help
This module adds support for the CNSS connectivity subsystem used
for wifi devices based on the QCA AR6320 chipset.
This driver also adds support to integrate WLAN module to subsystem
restart framework.
config CNSS_SDIO
bool "Enable/disable cnss sdio platform driver for wifi module"
depends on CNSS
depends on MMC
help
This module adds support for the CNSS wlan module interfaced
with SDIO bus.
This driver also adds support to integrate WLAN module to subsystem
restart framework, power on WLAN chip and registered the WLAN module
as a SDIO client device.
config CNSS_PCI
bool "Enable/disable cnss pci platform driver for wifi module"
depends on CNSS
depends on PCI
help
This module adds support for the CNSS wlan module interfaced
with PCIe bus.
This driver also adds support to integrate WLAN module to subsystem
restart framework, power on WLAN chip and registered the WLAN module
as a PCIe client device.
config CNSS_ASYNC
bool "Enable/disable cnss pci platform driver asynchronous probe"
depends on CNSS_PCI
help
If enabled, CNSS PCI platform driver would do asynchronous probe.
Using asynchronous probe will allow CNSS PCI platform driver to
probe in parallel with other device drivers and will help to
reduce kernel boot time.
config CNSS_MAC_BUG
bool "Enable/disable 0-4K memory initialization for QCA6174"
depends on CNSS
help
If enabled, 0-4K memory is reserved for QCA6174 to address
a MAC HW bug. MAC would do an invalid pointer fetch based on
the data, that was read from 0 to 4K. So fill it with zero's;
to an address for which PCIe root complex would honor the read
without any errors.
config CLD_DEBUG
bool "Enable/disable CLD debug features"
help
WLAN CLD driver uses this config to enable certain debug features.
Some of the debug features may affect performance or may compromise
on security.
Say N, if you are building a release kernel for production use.
Only say Y, if you are building a kernel with debug support.
config CLD_USB_CORE
tristate "Qualcomm Technologies Inc. Core wlan driver for QCA USB interface"
select WIRELESS_EXT
select WEXT_PRIV
select WEXT_CORE
select WEXT_SPY
select NL80211_TESTMODE
help
This section contains the necessary modules needed to enable the
core WLAN driver for Qualcomm Technologies Inc USB wlan chipset.
Select Y to compile the driver in order to have WLAN functionality
support.
config CLD_HL_SDIO_CORE
tristate "Qualcomm Technologies Inc. Core wlan driver for QCA SDIO interface"
select WIRELESS_EXT
select WEXT_PRIV
select WEXT_CORE
select WEXT_SPY
select NL80211_TESTMODE
depends on ARCH_QCOM
depends on MMC
config CLD_LL_CORE
tristate "Qualcomm Technologies Inc. Core wlan driver"
select NL80211_TESTMODE
select WEXT_CORE
select WEXT_PRIV
select WEXT_SPY
select WIRELESS_EXT
help
This section contains the necessary modules needed to enable the
core WLAN driver for Qualcomm Technologies Inc QCA6174 chipset.
Select Y to compile the driver in order to have WLAN functionality
support.
config CNSS_SECURE_FW
bool "Enable/Disable Memory Allocation for Secure Firmware Feature"
depends on CNSS
help
CLD Driver can use this for holding local copy of firmware
binaries which is used for sha crypto computation.
The Memory Allocation is done only if this Config Parameter is
enabled
config BUS_AUTO_SUSPEND
bool "Enable/Disable Runtime PM support for PCIe based WLAN Drivers"
depends on CNSS
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.
source "drivers/net/wireless/cnss/logger/Kconfig"
config WLAN_FEATURE_RX_WAKELOCK
bool "Enable RX wake lock feature"
help
Enable WLAN_FEATURE_HOLD_RX_WAKELOCK which is required to take rx
wakelock when driver receives packets from fw.

View file

@ -0,0 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Makefile for CNSS platform driver
#
obj-$(CONFIG_CNSS_PCI) += cnss_pci.o
obj-$(CONFIG_CNSS_SDIO) += cnss_sdio.o
obj-$(CONFIG_CNSS) += cnss_common.o
obj-$(CONFIG_CNSS_LOGGER) += logger/

View file

@ -0,0 +1,436 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/device.h>
#include <linux/pm_wakeup.h>
#include <linux/sched/debug.h>
#include <linux/suspend.h>
#include <linux/mutex.h>
#include <linux/rwsem.h>
#include <net/cnss.h>
#include "cnss_common.h"
#include <net/cfg80211.h>
#define AR6320_REV1_VERSION 0x5000000
#define AR6320_REV1_1_VERSION 0x5000001
#define AR6320_REV1_3_VERSION 0x5000003
#define AR6320_REV2_1_VERSION 0x5010000
#define AR6320_REV3_VERSION 0x5020000
#define AR6320_REV3_2_VERSION 0x5030000
#define AR900B_DEV_VERSION 0x1000000
#define QCA9377_REV1_1_VERSION 0x5020001
static struct cnss_fw_files FW_FILES_QCA6174_FW_1_1 = {
"qwlan11.bin", "bdwlan11.bin", "otp11.bin", "utf11.bin",
"utfbd11.bin", "epping11.bin", "evicted11.bin"};
static struct cnss_fw_files FW_FILES_QCA6174_FW_2_0 = {
"qwlan20.bin", "bdwlan20.bin", "otp20.bin", "utf20.bin",
"utfbd20.bin", "epping20.bin", "evicted20.bin"};
static struct cnss_fw_files FW_FILES_QCA6174_FW_1_3 = {
"qwlan13.bin", "bdwlan13.bin", "otp13.bin", "utf13.bin",
"utfbd13.bin", "epping13.bin", "evicted13.bin"};
static struct cnss_fw_files FW_FILES_QCA6174_FW_3_0 = {
"qwlan30.bin", "bdwlan30.bin", "otp30.bin", "utf30.bin",
"utfbd30.bin", "epping30.bin", "evicted30.bin"};
static struct cnss_fw_files FW_FILES_DEFAULT = {
"qwlan.bin", "bdwlan.bin", "otp.bin", "utf.bin",
"utfbd.bin", "epping.bin", "evicted.bin"};
enum cnss_dev_bus_type {
CNSS_BUS_NONE = -1,
CNSS_BUS_PCI,
CNSS_BUS_SDIO
};
static DEFINE_MUTEX(unsafe_channel_list_lock);
static DEFINE_MUTEX(dfs_nol_info_lock);
static struct cnss_unsafe_channel_list {
u16 unsafe_ch_count;
u16 unsafe_ch_list[CNSS_MAX_CH_NUM];
} unsafe_channel_list;
static struct cnss_dfs_nol_info {
void *dfs_nol_info;
u16 dfs_nol_info_len;
} dfs_nol_info;
static enum cnss_cc_src cnss_cc_source = CNSS_SOURCE_CORE;
int cnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count)
{
mutex_lock(&unsafe_channel_list_lock);
if (!unsafe_ch_list || ch_count > CNSS_MAX_CH_NUM) {
mutex_unlock(&unsafe_channel_list_lock);
return -EINVAL;
}
unsafe_channel_list.unsafe_ch_count = ch_count;
if (ch_count != 0) {
memcpy((char *)unsafe_channel_list.unsafe_ch_list,
(char *)unsafe_ch_list, ch_count * sizeof(u16));
}
mutex_unlock(&unsafe_channel_list_lock);
return 0;
}
EXPORT_SYMBOL(cnss_set_wlan_unsafe_channel);
int cnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list,
u16 *ch_count, u16 buf_len)
{
mutex_lock(&unsafe_channel_list_lock);
if (!unsafe_ch_list || !ch_count) {
mutex_unlock(&unsafe_channel_list_lock);
return -EINVAL;
}
if (buf_len < (unsafe_channel_list.unsafe_ch_count * sizeof(u16))) {
mutex_unlock(&unsafe_channel_list_lock);
return -ENOMEM;
}
*ch_count = unsafe_channel_list.unsafe_ch_count;
memcpy((char *)unsafe_ch_list,
(char *)unsafe_channel_list.unsafe_ch_list,
unsafe_channel_list.unsafe_ch_count * sizeof(u16));
mutex_unlock(&unsafe_channel_list_lock);
return 0;
}
EXPORT_SYMBOL(cnss_get_wlan_unsafe_channel);
int cnss_wlan_set_dfs_nol(const void *info, u16 info_len)
{
void *temp;
struct cnss_dfs_nol_info *dfs_info;
mutex_lock(&dfs_nol_info_lock);
if (!info || !info_len) {
mutex_unlock(&dfs_nol_info_lock);
return -EINVAL;
}
temp = kmemdup(info, info_len, GFP_KERNEL);
if (!temp) {
mutex_unlock(&dfs_nol_info_lock);
return -ENOMEM;
}
dfs_info = &dfs_nol_info;
kfree(dfs_info->dfs_nol_info);
dfs_info->dfs_nol_info = temp;
dfs_info->dfs_nol_info_len = info_len;
mutex_unlock(&dfs_nol_info_lock);
return 0;
}
EXPORT_SYMBOL(cnss_wlan_set_dfs_nol);
int cnss_wlan_get_dfs_nol(void *info, u16 info_len)
{
int len;
struct cnss_dfs_nol_info *dfs_info;
mutex_lock(&dfs_nol_info_lock);
if (!info || !info_len) {
mutex_unlock(&dfs_nol_info_lock);
return -EINVAL;
}
dfs_info = &dfs_nol_info;
if (!dfs_info->dfs_nol_info || dfs_info->dfs_nol_info_len == 0) {
mutex_unlock(&dfs_nol_info_lock);
return -ENOENT;
}
len = min(info_len, dfs_info->dfs_nol_info_len);
memcpy(info, dfs_info->dfs_nol_info, len);
mutex_unlock(&dfs_nol_info_lock);
return len;
}
EXPORT_SYMBOL(cnss_wlan_get_dfs_nol);
void cnss_init_work(struct work_struct *work, work_func_t func)
{
INIT_WORK(work, func);
}
EXPORT_SYMBOL(cnss_init_work);
void cnss_flush_work(void *work)
{
struct work_struct *cnss_work = work;
cancel_work_sync(cnss_work);
}
EXPORT_SYMBOL(cnss_flush_work);
void cnss_flush_delayed_work(void *dwork)
{
struct delayed_work *cnss_dwork = dwork;
cancel_delayed_work_sync(cnss_dwork);
}
EXPORT_SYMBOL(cnss_flush_delayed_work);
void cnss_pm_wake_lock_init(struct wakeup_source **ws, const char *name)
{
*ws = wakeup_source_register(NULL, name);
}
EXPORT_SYMBOL(cnss_pm_wake_lock_init);
void cnss_pm_wake_lock(struct wakeup_source *ws)
{
__pm_stay_awake(ws);
}
EXPORT_SYMBOL(cnss_pm_wake_lock);
void cnss_pm_wake_lock_timeout(struct wakeup_source *ws, ulong msec)
{
__pm_wakeup_event(ws, msec);
}
EXPORT_SYMBOL(cnss_pm_wake_lock_timeout);
void cnss_pm_wake_lock_release(struct wakeup_source *ws)
{
__pm_relax(ws);
}
EXPORT_SYMBOL(cnss_pm_wake_lock_release);
void cnss_pm_wake_lock_destroy(struct wakeup_source *ws)
{
wakeup_source_unregister(ws);
}
EXPORT_SYMBOL(cnss_pm_wake_lock_destroy);
void cnss_get_monotonic_boottime(struct timespec64 *ts)
{
ktime_get_boottime_ts64(ts);
}
EXPORT_SYMBOL(cnss_get_monotonic_boottime);
void cnss_get_boottime(struct timespec *ts)
{
ktime_get_ts(ts);
}
EXPORT_SYMBOL(cnss_get_boottime);
void cnss_init_delayed_work(struct delayed_work *work, work_func_t func)
{
INIT_DELAYED_WORK(work, func);
}
EXPORT_SYMBOL(cnss_init_delayed_work);
int cnss_vendor_cmd_reply(struct sk_buff *skb)
{
return cfg80211_vendor_cmd_reply(skb);
}
EXPORT_SYMBOL(cnss_vendor_cmd_reply);
int cnss_set_cpus_allowed_ptr(struct task_struct *task, ulong cpu)
{
return set_cpus_allowed_ptr(task, cpumask_of(cpu));
}
EXPORT_SYMBOL(cnss_set_cpus_allowed_ptr);
/* wlan prop driver cannot invoke show_stack
* function directly, so to invoke this function it
* call wcnss_dump_stack function
*/
void cnss_dump_stack(struct task_struct *task)
{
show_stack(task, NULL);
}
EXPORT_SYMBOL(cnss_dump_stack);
struct cnss_dev_platform_ops *cnss_get_platform_ops(struct device *dev)
{
if (!dev)
return NULL;
else
return dev->platform_data;
}
int cnss_common_request_bus_bandwidth(struct device *dev, int bandwidth)
{
struct cnss_dev_platform_ops *pf_ops = cnss_get_platform_ops(dev);
if (pf_ops && pf_ops->request_bus_bandwidth)
return pf_ops->request_bus_bandwidth(bandwidth);
else
return -EINVAL;
}
EXPORT_SYMBOL(cnss_common_request_bus_bandwidth);
void *cnss_common_get_virt_ramdump_mem(struct device *dev, unsigned long *size)
{
struct cnss_dev_platform_ops *pf_ops = cnss_get_platform_ops(dev);
if (pf_ops && pf_ops->get_virt_ramdump_mem)
return pf_ops->get_virt_ramdump_mem(size);
else
return NULL;
}
EXPORT_SYMBOL(cnss_common_get_virt_ramdump_mem);
void cnss_common_device_self_recovery(struct device *dev)
{
struct cnss_dev_platform_ops *pf_ops = cnss_get_platform_ops(dev);
if (pf_ops && pf_ops->device_self_recovery)
pf_ops->device_self_recovery();
}
EXPORT_SYMBOL(cnss_common_device_self_recovery);
void cnss_common_schedule_recovery_work(struct device *dev)
{
struct cnss_dev_platform_ops *pf_ops = cnss_get_platform_ops(dev);
if (pf_ops && pf_ops->schedule_recovery_work)
pf_ops->schedule_recovery_work();
}
EXPORT_SYMBOL(cnss_common_schedule_recovery_work);
void cnss_common_device_crashed(struct device *dev)
{
struct cnss_dev_platform_ops *pf_ops = cnss_get_platform_ops(dev);
if (pf_ops && pf_ops->device_crashed)
pf_ops->device_crashed();
}
EXPORT_SYMBOL(cnss_common_device_crashed);
u8 *cnss_common_get_wlan_mac_address(struct device *dev, u32 *num)
{
struct cnss_dev_platform_ops *pf_ops = cnss_get_platform_ops(dev);
if (pf_ops && pf_ops->get_wlan_mac_address)
return pf_ops->get_wlan_mac_address(num);
else
return NULL;
}
EXPORT_SYMBOL(cnss_common_get_wlan_mac_address);
int cnss_common_set_wlan_mac_address(struct device *dev, const u8 *in, u32 len)
{
struct cnss_dev_platform_ops *pf_ops = cnss_get_platform_ops(dev);
if (pf_ops && pf_ops->set_wlan_mac_address)
return pf_ops->set_wlan_mac_address(in, len);
else
return -EINVAL;
}
EXPORT_SYMBOL(cnss_common_set_wlan_mac_address);
int cnss_power_up(struct device *dev)
{
struct cnss_dev_platform_ops *pf_ops = cnss_get_platform_ops(dev);
if (pf_ops && pf_ops->power_up)
return pf_ops->power_up(dev);
else
return -EINVAL;
}
EXPORT_SYMBOL(cnss_power_up);
int cnss_power_down(struct device *dev)
{
struct cnss_dev_platform_ops *pf_ops = cnss_get_platform_ops(dev);
if (pf_ops && pf_ops->power_down)
return pf_ops->power_down(dev);
else
return -EINVAL;
}
EXPORT_SYMBOL(cnss_power_down);
void cnss_get_qca9377_fw_files(struct cnss_fw_files *pfw_files,
u32 size, u32 tufello_dual_fw)
{
if (tufello_dual_fw)
memcpy(pfw_files, &FW_FILES_DEFAULT, sizeof(*pfw_files));
else
memcpy(pfw_files, &FW_FILES_QCA6174_FW_3_0, sizeof(*pfw_files));
}
EXPORT_SYMBOL(cnss_get_qca9377_fw_files);
int cnss_get_fw_files_for_target(struct cnss_fw_files *pfw_files,
u32 target_type, u32 target_version)
{
if (!pfw_files)
return -ENODEV;
switch (target_version) {
case AR6320_REV1_VERSION:
case AR6320_REV1_1_VERSION:
memcpy(pfw_files, &FW_FILES_QCA6174_FW_1_1, sizeof(*pfw_files));
break;
case AR6320_REV1_3_VERSION:
memcpy(pfw_files, &FW_FILES_QCA6174_FW_1_3, sizeof(*pfw_files));
break;
case AR6320_REV2_1_VERSION:
memcpy(pfw_files, &FW_FILES_QCA6174_FW_2_0, sizeof(*pfw_files));
break;
case AR6320_REV3_VERSION:
case AR6320_REV3_2_VERSION:
memcpy(pfw_files, &FW_FILES_QCA6174_FW_3_0, sizeof(*pfw_files));
break;
default:
memcpy(pfw_files, &FW_FILES_DEFAULT, sizeof(*pfw_files));
pr_err("%s default version 0x%X 0x%X\n", __func__,
target_type, target_version);
break;
}
return 0;
}
EXPORT_SYMBOL(cnss_get_fw_files_for_target);
void cnss_set_cc_source(enum cnss_cc_src cc_source)
{
cnss_cc_source = cc_source;
}
EXPORT_SYMBOL(cnss_set_cc_source);
enum cnss_cc_src cnss_get_cc_source(void)
{
return cnss_cc_source;
}
EXPORT_SYMBOL(cnss_get_cc_source);
const char *cnss_wlan_get_evicted_data_file(void)
{
return FW_FILES_QCA6174_FW_3_0.evicted_data;
}
int cnss_common_register_tsf_captured_handler(struct device *dev,
irq_handler_t handler, void *ctx)
{
struct cnss_dev_platform_ops *pf_ops = cnss_get_platform_ops(dev);
if (pf_ops && pf_ops->register_tsf_captured_handler)
return pf_ops->register_tsf_captured_handler(handler, ctx);
else
return -EINVAL;
}
EXPORT_SYMBOL(cnss_common_register_tsf_captured_handler);
int cnss_common_unregister_tsf_captured_handler(struct device *dev,
void *ctx)
{
struct cnss_dev_platform_ops *pf_ops = cnss_get_platform_ops(dev);
if (pf_ops && pf_ops->unregister_tsf_captured_handler)
return pf_ops->unregister_tsf_captured_handler(ctx);
else
return -EINVAL;
}
EXPORT_SYMBOL(cnss_common_unregister_tsf_captured_handler);

View file

@ -0,0 +1,56 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
#ifndef _NET_CNSS_COMMON_H_
#define _NET_CNSS_COMMON_H_
/* max 20mhz channel count */
#define CNSS_MAX_CH_NUM 45
struct cnss_cap_tsf_info {
int irq_num;
void *context;
irq_handler_t irq_handler;
};
struct cnss_dev_platform_ops {
int (*request_bus_bandwidth)(int bandwidth);
void* (*get_virt_ramdump_mem)(unsigned long *size);
void (*device_self_recovery)(void);
void (*schedule_recovery_work)(void);
void (*device_crashed)(void);
u8 * (*get_wlan_mac_address)(u32 *num);
int (*set_wlan_mac_address)(const u8 *in, u32 len);
int (*power_up)(struct device *dev);
int (*power_down)(struct device *dev);
int (*register_tsf_captured_handler)(irq_handler_t handler,
void *adapter);
int (*unregister_tsf_captured_handler)(void *adapter);
};
int cnss_pci_request_bus_bandwidth(int bandwidth);
int cnss_sdio_request_bus_bandwidth(int bandwidth);
void cnss_sdio_device_crashed(void);
void cnss_pci_device_crashed(void);
void cnss_pci_device_self_recovery(void);
void cnss_sdio_device_self_recovery(void);
void *cnss_pci_get_virt_ramdump_mem(unsigned long *size);
void *cnss_sdio_get_virt_ramdump_mem(unsigned long *size);
void cnss_sdio_schedule_recovery_work(void);
void cnss_pci_schedule_recovery_work(void);
int cnss_pcie_set_wlan_mac_address(const u8 *in, u32 len);
int cnss_sdio_set_wlan_mac_address(const u8 *in, u32 len);
u8 *cnss_pci_get_wlan_mac_address(u32 *num);
u8 *cnss_sdio_get_wlan_mac_address(u32 *num);
int cnss_sdio_power_up(struct device *dev);
int cnss_sdio_power_down(struct device *dev);
int cnss_pcie_power_up(struct device *dev);
int cnss_pcie_power_down(struct device *dev);
const char *cnss_wlan_get_evicted_data_file(void);
#endif /* _NET_CNSS_COMMON_H_ */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# cnss logger configuration
#
config CNSS_LOGGER
tristate "CNSS Logging Service Driver"
help
This module adds support for the CNSS Logging Service for CLD
driver, including the netlink socket service registration, transmit,
event receive.

View file

@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Makefile for cnss logger
#
obj-$(CONFIG_CNSS_LOGGER) += logger.o
logger-y += main.o \
nl_service.o
logger-$(CONFIG_DEBUG_FS) += debugfs.o

View file

@ -0,0 +1,125 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
#include <linux/module.h>
#include <linux/debugfs.h>
#include "logger.h"
#define CNSS_LOGGER_STATE_DUMP_BUFFER (2 * 1024) /* 2KB */
static int logger_state_dump_device(struct logger_device *dev, char *buf,
int buf_len)
{
int len = 0;
struct logger_event_handler *cur;
len += scnprintf(buf + len, buf_len - len,
"==============================================\n");
len += scnprintf(buf + len, buf_len - len,
"driver [%s] is registered with radio index: %d\n",
dev->name, dev->radio_idx);
if (list_empty(&dev->event_list)) {
len += scnprintf(buf + len, buf_len - len,
"No event registered\n");
return len;
}
list_for_each_entry(cur, &dev->event_list, list) {
len += scnprintf(buf + len, buf_len - len,
"\t event %d\n", cur->event);
}
len += scnprintf(buf + len, buf_len - len, "\n");
return len;
}
static int logger_state_dump(struct logger_context *ctx, char *buf, int buf_len)
{
int len = 0;
struct logger_device *cur;
if (list_empty(&ctx->dev_list)) {
len += scnprintf(buf + len, buf_len - len,
"=======================\n");
len += scnprintf(buf + len, buf_len - len,
"No driver registered\n");
return 0;
}
list_for_each_entry(cur, &ctx->dev_list, list)
len += logger_state_dump_device(cur, (buf + len), buf_len);
return 0;
}
static int logger_state_open(struct inode *inode, struct file *file)
{
struct logger_context *ctx = inode->i_private;
void *buf;
int ret;
mutex_lock(&ctx->con_mutex);
buf = kmalloc(CNSS_LOGGER_STATE_DUMP_BUFFER, GFP_KERNEL);
if (!buf) {
ret = -ENOMEM;
goto error_unlock;
}
ret = logger_state_dump(ctx, buf, CNSS_LOGGER_STATE_DUMP_BUFFER);
if (ret)
goto error_free;
file->private_data = buf;
mutex_unlock(&ctx->con_mutex);
return 0;
error_free:
kfree(buf);
error_unlock:
mutex_unlock(&ctx->con_mutex);
return ret;
}
static int logger_state_release(struct inode *inode, struct file *file)
{
kfree(file->private_data);
return 0;
}
static ssize_t logger_state_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
const char *buf = file->private_data;
unsigned int len = strlen(buf);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static const struct file_operations fops_logger_state = {
.open = logger_state_open,
.release = logger_state_release,
.read = logger_state_read,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
void logger_debugfs_init(struct logger_context *ctx)
{
if (!ctx->debugfs_entry)
ctx->debugfs_entry = debugfs_create_dir("cnss_logger", NULL);
debugfs_create_file("state", 0400, ctx->debugfs_entry, ctx,
&fops_logger_state);
}
void logger_debugfs_remove(struct logger_context *ctx)
{
debugfs_remove(ctx->debugfs_entry);
}

View file

@ -0,0 +1,94 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
#ifndef _LOGGER_H_
#define _LOGGER_H_
#include <linux/module.h>
#include <linux/list.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#define CNSS_LOGGER_NL_MCAST_GRP_ID 0x01
#define CNSS_LOGGER_NL_MAX_PAYLOAD 256
#define CNSS_LOGGER_BROADCAST_ID 255
/**
* struct aninlmsg - the wireless service message header
* @nlh: the netlink message header
* @radio: the radio index of this message
* @wmsg: the pointer to the wireless message data
*/
struct aninlmsg {
struct nlmsghdr *nlh;
int radio;
void *wmsg;
};
/**
* struct logger_event_handler - the logger event handler structure
* @list: the event list associated to the same device
* @event: the event number
* @radio_idx: the callback handler
*/
struct logger_event_handler {
struct list_head list;
int event;
int (*cb)(struct sk_buff *skb);
};
/**
* struct logger_device - the logger device structure
* @list: the device list registered to logger module
* @event_list: the event list registered to this device
* @ctx: the pointer to the logger context
* @wiphy: the wiphy that associated to the device
* @name: the name of the device driver module
* @radio_idx: the radio index assigned to this device
*/
struct logger_device {
struct list_head list;
struct list_head event_list;
struct logger_context *ctx;
struct wiphy *wiphy;
char name[MODULE_NAME_LEN];
int radio_idx;
};
/**
* struct logger_context - the main context block for logger module
* @dev_list: this is the list to maintain the devices that registered
* to use the logger module feature
* @nl_sock: the netlink socket to share accros the module
* @con_mutex: the mutex to protect concurrent access
* @data_lock: the lock to protect shared data
* @radio_mask: this mask would maintain the radio index assign and release
*/
struct logger_context {
struct list_head dev_list;
struct sock *nl_sock;
struct mutex con_mutex; /* concurrent access mutex */
spinlock_t data_lock;
unsigned long radio_mask; /* support up to 4 drivers registration? */
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_entry;
#endif
};
int logger_netlink_init(struct logger_context *ctx);
int logger_netlink_deinit(struct logger_context *ctx);
struct logger_context *logger_get_ctx(void);
#ifdef CONFIG_DEBUG_FS
void logger_debugfs_init(struct logger_context *ctx);
void logger_debugfs_remove(struct logger_context *ctx);
#else
static inline void logger_debugfs_init(struct logger_context *ctx) {}
static inline void logger_debugfs_remove(struct logger_context *ctx) {}
#endif
#endif /* _LOGGER_H_ */

View file

@ -0,0 +1,47 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/export.h>
#include <net/cnss_logger.h>
#include "logger.h"
static struct logger_context *ctx;
struct logger_context *logger_get_ctx(void)
{
return ctx;
}
static int __init logger_module_init(void)
{
int ret;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ret = logger_netlink_init(ctx);
mutex_init(&ctx->con_mutex);
spin_lock_init(&ctx->data_lock);
logger_debugfs_init(ctx);
return ret;
}
static void __exit logger_module_exit(void)
{
logger_debugfs_remove(ctx);
logger_netlink_deinit(ctx);
kfree(ctx);
}
module_init(logger_module_init);
module_exit(logger_module_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CNSS Logging Service Driver");

View file

@ -0,0 +1,467 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
#define pr_fmt(fmt) "cnss_logger: %s: " fmt, __func__
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/export.h>
#include <net/cnss_logger.h>
#include "logger.h"
static DEFINE_MUTEX(logger_sem);
/**
* logger_get_radio_idx() - to get the radio index
* @ctx: the logger context pointer
*
* Return: the first available radio index, otherwise failure code
*/
static int logger_get_radio_idx(struct logger_context *ctx)
{
int i;
for (i = 0; i < sizeof(ctx->radio_mask); i++) {
if (!test_and_set_bit(i, &ctx->radio_mask))
return i;
}
return -EINVAL;
}
/**
* logger_put_radio_idx() - to release the radio index
* @radio: the radio index to release
*
* Return: None
*/
static void logger_put_radio_idx(struct logger_context *ctx, int radio)
{
clear_bit(radio, &ctx->radio_mask);
}
/**
* logger_get_device() - to get the logger device per radio index
* @radio: the radio index
*
* Return: the logger_device pointer, otherwise return NULL.
*/
static struct logger_device *logger_get_device(int radio)
{
struct logger_device *dev;
struct logger_context *ctx;
ctx = logger_get_ctx();
if (!ctx)
return NULL;
list_for_each_entry(dev, &ctx->dev_list, list) {
if (dev->radio_idx == radio)
return dev;
}
return NULL;
}
/**
* logger_device_is_registered() - to check if device has been registered
* @dev: pointer to logger device
* @wiphy: the wiphy pointer of the device to register
*
* This helper function is to check if this device has been registered.
*
* Return: NULL if it has not, otherwise return the logger_device pointer.
*/
static
struct logger_device *logger_device_is_registered(struct logger_context *ctx,
struct wiphy *wiphy)
{
struct logger_device *dev;
list_for_each_entry(dev, &ctx->dev_list, list) {
if (dev->wiphy == wiphy)
return dev;
}
return NULL;
}
/**
* logger_dispatch_skb() - to dispatch the skb to devices
* @skb: the socket buffer received and to dispatch
*
* The function will look up the header of the skb, and dispatch the skb
* to the associated event and device that registered.
*
* Return: 0 if successfully dispatch, otherwise failure code
*/
static int logger_dispatch_skb(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
struct logger_context *ctx;
struct logger_device *cur;
struct logger_event_handler *evt;
int handled = 0;
ctx = logger_get_ctx();
if (!ctx)
return -ENOENT;
pr_info("skb_len: %d, skb_data_len: %d\n",
skb->len, skb->data_len);
if (skb->len < sizeof(struct nlmsghdr))
return 0;
nlh = (struct nlmsghdr *)skb->data;
list_for_each_entry(cur, &ctx->dev_list, list) {
list_for_each_entry(evt, &cur->event_list, list) {
if (nlh->nlmsg_type == evt->event) {
if (evt->cb) {
handled = 1;
evt->cb(skb);
}
/* Break inside loop, next dev */
break;
}
}
}
if (!handled)
pr_info("Not handled msg type: %d\n", nlh->nlmsg_type);
return 0;
}
/**
* logger_flush_event_handle() - to flush the event handle associate to device
* @dev: pointer to logger device
*
* The function will clean up all the event handle's resource, take it out
* from the list, and free the memory allocated.
*
* Return: None
*/
static void logger_flush_event_handle(struct logger_device *dev)
{
struct list_head *pos, *temp;
struct logger_event_handler *cur;
list_for_each_safe(pos, temp, &dev->event_list) {
cur = container_of(pos, struct logger_event_handler, list);
pr_info("radio: %d, event: %d unregistered\n",
dev->radio_idx, cur->event);
list_del(&cur->list);
kfree(cur);
}
}
/**
* logger_flush_devices() - to flush the devices infomration
* @dev: pointer to logger device
*
* The helper function to flush the device information, all the device clean
* up prcoess should be starting from here.
*
* Return: None
*/
static void logger_flush_devices(struct logger_device *dev)
{
pr_info("driver: [%s] and radio-%d is unregistered\n",
dev->name, dev->radio_idx);
logger_flush_event_handle(dev);
logger_put_radio_idx(dev->ctx, dev->radio_idx);
list_del(&dev->list);
kfree(dev);
}
/**
* logger_register_device_event() - register the evet to device
* @dev: pointer to logger device
* @event: the event to register
* @cb: the callback associated to the device and event
*
* Return: 0 if register successfully, otherwise the failure code
*/
static int logger_register_device_event(struct logger_device *dev, int event,
int (*cb)(struct sk_buff *skb))
{
struct logger_event_handler *cur;
list_for_each_entry(cur, &dev->event_list, list) {
if (cur->event == event) {
pr_info("event %d, is already added\n", event);
return 0;
}
}
cur = kmalloc(sizeof(*cur), GFP_KERNEL);
if (!cur)
return -ENOMEM;
cur->event = event;
cur->cb = cb;
pr_info("radio: %d, event: %d\n", dev->radio_idx, cur->event);
list_add_tail(&cur->list, &dev->event_list);
return 0;
}
/**
* logger_unregister_device_event() - unregister the evet from device
* @dev: pointer to logger device
* @event: the event to unregister
* @cb: the callback associated to the device and event
*
* Return: 0 if unregister successfully, otherwise the failure code
*/
static int logger_unregister_device_event(struct logger_device *dev, int event,
int (*cb)(struct sk_buff *skb))
{
struct list_head *pos, *temp;
struct logger_event_handler *cur;
list_for_each_safe(pos, temp, &dev->event_list) {
cur = container_of(pos, struct logger_event_handler, list);
if (cur->event == event && cur->cb == cb) {
pr_info("radio: %d, event: %d\n",
dev->radio_idx, cur->event);
list_del(&cur->list);
kfree(cur);
return 0;
}
}
return -ENOENT;
}
/**
* logger_skb_input() - the callback to receive the skb
* @skb: the receive socket buffer
*
* Return: None
*/
static void logger_skb_input(struct sk_buff *skb)
{
mutex_lock(&logger_sem);
logger_dispatch_skb(skb);
mutex_unlock(&logger_sem);
}
/**
* cnss_logger_event_register() - register the event
* @radio: the radio index to register
* @event: the event to register
* @cb: the callback
*
* This function is used to register event associated to the radio index.
*
* Return: 0 if register success, otherwise failure code
*/
int cnss_logger_event_register(int radio, int event,
int (*cb)(struct sk_buff *skb))
{
int ret = -ENOENT;
struct logger_device *dev;
dev = logger_get_device(radio);
if (dev)
ret = logger_register_device_event(dev, event, cb);
return ret;
}
EXPORT_SYMBOL(cnss_logger_event_register);
/**
* cnss_logger_event_unregister() - unregister the event
* @radio: the radio index to unregister
* @event: the event to unregister
* @cb: the callback
*
* This function is used to unregister the event from cnss logger module.
*
* Return: 0 if unregister success, otherwise failure code
*/
int cnss_logger_event_unregister(int radio, int event,
int (*cb)(struct sk_buff *skb))
{
int ret = -ENOENT;
struct logger_device *dev;
dev = logger_get_device(radio);
if (dev)
ret = logger_unregister_device_event(dev, event, cb);
return ret;
}
EXPORT_SYMBOL(cnss_logger_event_unregister);
/**
* cnss_logger_device_register() - register the driver
* @wiphy: the wiphy device to unregister
* @name: the module name of the driver
*
* This function is used to register the driver to cnss logger module,
* this will indicate the existence of the driver, and also assign the
* radio index for further operation.
*
* Return: the radio index if register successful, otherwise failure code
*/
int cnss_logger_device_register(struct wiphy *wiphy, const char *name)
{
int radio;
struct logger_context *ctx;
struct logger_device *new;
ctx = logger_get_ctx();
if (!ctx)
return -ENOENT;
/* sanity check, already registered? */
new = logger_device_is_registered(ctx, wiphy);
if (new)
return new->radio_idx;
radio = logger_get_radio_idx(ctx);
if (radio < 0) {
pr_err("driver registration is full\n");
return -ENOMEM;
}
new = kmalloc(sizeof(*new), GFP_KERNEL);
if (!new) {
logger_put_radio_idx(ctx, radio);
return -ENOMEM;
}
new->radio_idx = radio;
new->wiphy = wiphy;
new->ctx = ctx;
strlcpy(new->name, name, sizeof(new->name));
INIT_LIST_HEAD(&new->event_list);
list_add(&new->list, &ctx->dev_list);
pr_info("driver: [%s] is registered as radio-%d\n",
new->name, new->radio_idx);
return new->radio_idx;
}
EXPORT_SYMBOL(cnss_logger_device_register);
/**
* cnss_logger_device_unregister() - unregister the driver
* @radio: the radio to unregister
* @wiphy: the wiphy device to unregister
*
* This function is used to unregister the driver from cnss logger module.
* This will disable the driver to access the interface in cnss logger,
* and also all the related events that registered will be reset.
*
* Return: 0 if success, otherwise failure code
*/
int cnss_logger_device_unregister(int radio, struct wiphy *wiphy)
{
struct logger_context *ctx;
struct logger_device *cur;
struct list_head *pos, *temp;
ctx = logger_get_ctx();
if (!ctx)
return -ENOENT;
list_for_each_safe(pos, temp, &ctx->dev_list) {
cur = list_entry(pos, struct logger_device, list);
if (cur->radio_idx == radio && cur->wiphy == wiphy) {
logger_flush_devices(cur);
break;
}
}
return 0;
}
EXPORT_SYMBOL(cnss_logger_device_unregister);
/**
* cnss_logger_nl_ucast() - nl interface to unicast the buffer
* @skb: the socket buffer to transmit
* @portid: netlink portid of the destination socket
* @flag: the flag to indicate if this is a nonblock call
*
* Return: 0 if success, otherwise failure code
*/
int cnss_logger_nl_ucast(struct sk_buff *skb, int portid, int flag)
{
struct logger_context *ctx;
ctx = logger_get_ctx();
if (!ctx) {
dev_kfree_skb(skb);
return -ENOENT;
}
return netlink_unicast(ctx->nl_sock, skb, portid, flag);
}
EXPORT_SYMBOL(cnss_logger_nl_ucast);
/**
* cnss_logger_nl_bcast() - nl interface to broadcast the buffer
* @skb: the socket buffer to transmit
* @portid: netlink portid of the destination socket
* @flag: the gfp_t flag
*
* Return: 0 if success, otherwise failure code
*/
int cnss_logger_nl_bcast(struct sk_buff *skb, int portid, int flag)
{
struct logger_context *ctx;
ctx = logger_get_ctx();
if (!ctx) {
dev_kfree_skb(skb);
return -ENOENT;
}
return netlink_broadcast(ctx->nl_sock, skb, 0, portid, flag);
}
EXPORT_SYMBOL(cnss_logger_nl_bcast);
/**
* logger_netlink_init() - initialize the netlink socket
* @ctx: the cnss logger context pointer
*
* Return: the netlink handle if success, otherwise failure code
*/
int logger_netlink_init(struct logger_context *ctx)
{
struct netlink_kernel_cfg cfg = {
.groups = CNSS_LOGGER_NL_MCAST_GRP_ID,
.input = logger_skb_input,
};
ctx->nl_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, &cfg);
if (!ctx->nl_sock) {
pr_err("cnss_logger: Cannot create netlink socket\n");
return -ENOMEM;
}
INIT_LIST_HEAD(&ctx->dev_list);
return 0;
}
/**
* logger_netlink_deinit() - release the netlink socket and other resource
* @ctx: the cnss logger context pointer
*
* Return: 0 if success, otherwise failure code
*/
int logger_netlink_deinit(struct logger_context *ctx)
{
struct list_head *pos, *temp;
struct logger_device *dev;
netlink_kernel_release(ctx->nl_sock);
list_for_each_safe(pos, temp, &ctx->dev_list) {
dev = container_of(pos, struct logger_device, list);
logger_flush_devices(dev);
}
return 0;
}

View file

@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Makefile for cnss crypto
#
obj-$(CONFIG_CNSS_CRYPTO) += cnss_secif.o

View file

@ -0,0 +1,161 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2011-2013, 2015, 2018-2021, The Linux Foundation. */
#include <linux/export.h>
#include <linux/qcomwlan_secif.h>
#include <crypto/aes.h>
/* APIs for calling crypto routines from kernel
*/
struct crypto_ahash *wcnss_wlan_crypto_alloc_ahash(const char *alg_name,
u32 type, u32 mask)
{
return crypto_alloc_ahash(alg_name, type, mask);
}
EXPORT_SYMBOL(wcnss_wlan_crypto_alloc_ahash);
int wcnss_wlan_crypto_ahash_digest(struct ahash_request *req)
{
return crypto_ahash_digest(req);
}
EXPORT_SYMBOL(wcnss_wlan_crypto_ahash_digest);
void wcnss_wlan_crypto_free_ahash(struct crypto_ahash *tfm)
{
crypto_free_ahash(tfm);
}
EXPORT_SYMBOL(wcnss_wlan_crypto_free_ahash);
int wcnss_wlan_crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen)
{
return crypto_ahash_setkey(tfm, key, keylen);
}
EXPORT_SYMBOL(wcnss_wlan_crypto_ahash_setkey);
void wcnss_wlan_ablkcipher_request_free(struct ablkcipher_request *req)
{
ablkcipher_request_free(req);
}
EXPORT_SYMBOL(wcnss_wlan_ablkcipher_request_free);
void wcnss_wlan_crypto_free_ablkcipher(struct crypto_ablkcipher *tfm)
{
crypto_free_ablkcipher(tfm);
}
EXPORT_SYMBOL(wcnss_wlan_crypto_free_ablkcipher);
void wcnss_wlan_crypto_free_cipher(struct crypto_cipher *tfm)
{
crypto_free_cipher(tfm);
}
EXPORT_SYMBOL(wcnss_wlan_crypto_free_cipher);
struct crypto_cipher *
wcnss_wlan_crypto_alloc_cipher(const char *alg_name, u32 type, u32 mask)
{
return crypto_alloc_cipher(alg_name, type, mask);
}
EXPORT_SYMBOL(wcnss_wlan_crypto_alloc_cipher);
static inline void xor_128(const u8 *a, const u8 *b, u8 *out)
{
u8 i;
for (i = 0; i < AES_BLOCK_SIZE; i++)
out[i] = a[i] ^ b[i];
}
static inline void leftshift_onebit(const u8 *input, u8 *output)
{
int i, overflow = 0;
for (i = (AES_BLOCK_SIZE - 1); i >= 0; i--) {
output[i] = input[i] << 1;
output[i] |= overflow;
overflow = (input[i] & 0x80) ? 1 : 0;
}
}
static void generate_subkey(struct crypto_cipher *tfm, u8 *k1, u8 *k2)
{
u8 l[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
u8 const_rb[AES_BLOCK_SIZE] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87};
u8 const_zero[AES_BLOCK_SIZE] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
crypto_cipher_encrypt_one(tfm, l, const_zero);
if ((l[0] & 0x80) == 0) { /* If MSB(l) = 0, then k1 = l << 1 */
leftshift_onebit(l, k1);
} else { /* Else k1 = ( l << 1 ) (+) Rb */
leftshift_onebit(l, tmp);
xor_128(tmp, const_rb, k1);
}
if ((k1[0] & 0x80) == 0) {
leftshift_onebit(k1, k2);
} else {
leftshift_onebit(k1, tmp);
xor_128(tmp, const_rb, k2);
}
}
static inline void padding(u8 *lastb, u8 *pad, u16 length)
{
u8 j;
/* original last block */
for (j = 0; j < AES_BLOCK_SIZE; j++) {
if (j < length)
pad[j] = lastb[j];
else if (j == length)
pad[j] = 0x80;
else
pad[j] = 0x00;
}
}
void wcnss_wlan_cmac_calc_mic(struct crypto_cipher *tfm, u8 *m,
u16 length, u8 *mac)
{
u8 x[AES_BLOCK_SIZE], y[AES_BLOCK_SIZE];
u8 m_last[AES_BLOCK_SIZE], padded[AES_BLOCK_SIZE];
u8 k1[AES_KEYSIZE_128], k2[AES_KEYSIZE_128];
int cmpBlk;
int i, nblocks = (length + 15) / AES_BLOCK_SIZE;
generate_subkey(tfm, k1, k2);
if (nblocks == 0) {
nblocks = 1;
cmpBlk = 0;
} else {
cmpBlk = ((length % AES_BLOCK_SIZE) == 0) ? 1 : 0;
}
if (cmpBlk) { /* Last block is complete block */
xor_128(&m[AES_BLOCK_SIZE * (nblocks - 1)], k1, m_last);
} else { /* Last block is not complete block */
padding(&m[AES_BLOCK_SIZE * (nblocks - 1)], padded,
length % AES_BLOCK_SIZE);
xor_128(padded, k2, m_last);
}
for (i = 0; i < AES_BLOCK_SIZE; i++)
x[i] = 0;
for (i = 0; i < (nblocks - 1); i++) {
xor_128(x, &m[AES_BLOCK_SIZE * i], y); /* y = Mi (+) x */
crypto_cipher_encrypt_one(tfm, x, y); /* x = AES-128(KEY, y) */
}
xor_128(x, m_last, y);
crypto_cipher_encrypt_one(tfm, x, y);
memcpy(mac, x, CMAC_TLEN);
}
EXPORT_SYMBOL(wcnss_wlan_cmac_calc_mic);

View file

@ -0,0 +1,86 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2014, 2017-2021, The Linux Foundation. All rights reserved. */
#ifndef __ESOC_CLIENT_H_
#define __ESOC_CLIENT_H_
#include <linux/device.h>
#include <linux/esoc_ctrl.h>
#include <linux/notifier.h>
enum esoc_client_hook_prio {
ESOC_MHI_HOOK,
ESOC_CNSS_HOOK,
ESOC_MAX_HOOKS
};
struct esoc_link_data {
enum esoc_client_hook_prio prio;
__u64 link_id;
};
/* Flag values used with the power_on and power_off hooks */
#define ESOC_HOOK_MDM_CRASH 0x0001 /* In crash handling path */
#define ESOC_HOOK_MDM_DOWN 0x0002 /* MDM about to go down */
struct esoc_client_hook {
char *name;
void *priv;
enum esoc_client_hook_prio prio;
int (*esoc_link_power_on)(void *priv, unsigned int flags);
void (*esoc_link_power_off)(void *priv, unsigned int flags);
u64 (*esoc_link_get_id)(void *priv);
void (*esoc_link_mdm_crash)(void *priv);
};
/*
* struct esoc_desc: Describes an external soc
* @name: external soc name
* @priv: private data for external soc
*/
struct esoc_desc {
const char *name;
const char *link;
const char *link_info;
void *priv;
};
#ifdef CONFIG_ESOC_CLIENT
/* Can return probe deferral */
struct esoc_desc *devm_register_esoc_client(struct device *dev, const char *name);
void devm_unregister_esoc_client(struct device *dev, struct esoc_desc *esoc_desc);
int esoc_register_client_notifier(struct notifier_block *nb);
int esoc_register_client_hook(struct esoc_desc *desc,
struct esoc_client_hook *client_hook);
int esoc_unregister_client_hook(struct esoc_desc *desc,
struct esoc_client_hook *client_hook);
#else
static inline struct esoc_desc *devm_register_esoc_client(struct device *dev,
const char *name)
{
return NULL;
}
static inline void devm_unregister_esoc_client(struct device *dev,
struct esoc_desc *esoc_desc)
{
}
static inline int esoc_register_client_notifier(struct notifier_block *nb)
{
return -EIO;
}
static inline int esoc_register_client_hook(struct esoc_desc *desc,
struct esoc_client_hook *client_hook)
{
return -EIO;
}
static inline int esoc_unregister_client_hook(struct esoc_desc *desc,
struct esoc_client_hook *client_hook)
{
return -EIO;
}
#endif
#endif

View file

@ -0,0 +1,32 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2011-2013, 2019-2021,The Linux Foundation. All rights reserved. */
#ifndef __QCOM_WLAN_SECIF_H__
#define __QCOM_WLAN_SECIF_H__
#include <crypto/hash.h>
#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
/*
* Prototypes for WLAN Security Interface Functions
*/
struct crypto_ahash *
wcnss_wlan_crypto_alloc_ahash(const char *alg_name, u32 type, u32 mask);
int wcnss_wlan_crypto_ahash_digest(struct ahash_request *req);
void wcnss_wlan_crypto_free_ahash(struct crypto_ahash *tfm);
int wcnss_wlan_crypto_ahash_setkey(struct crypto_ahash *tfm,
const u8 *key, unsigned int keylen);
struct crypto_ablkcipher *
wcnss_wlan_crypto_alloc_ablkcipher(const char *alg_name, u32 type, u32 mask);
void wcnss_wlan_ablkcipher_request_free(struct ablkcipher_request *req);
void wcnss_wlan_crypto_free_cipher(struct crypto_cipher *tfm);
void wcnss_wlan_crypto_free_ablkcipher(struct crypto_ablkcipher *tfm);
struct crypto_cipher *
wcnss_wlan_crypto_alloc_cipher(const char *alg_name, u32 type, u32 mask);
void wcnss_wlan_cmac_calc_mic(struct crypto_cipher *tfm, u8 *m,
u16 length, u8 *mac);
#endif /* __QCOM_WLAN_SECIF_H__ */

253
include/net/cnss.h Normal file
View file

@ -0,0 +1,253 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2013-2021, The Linux Foundation. All rights reserved. */
#ifndef _NET_CNSS_H_
#define _NET_CNSS_H_
#include <linux/device.h>
#include <linux/skbuff.h>
#include <linux/pci.h>
#include <linux/mmc/sdio_func.h>
#include <linux/interrupt.h>
#ifdef CONFIG_CNSS
#define MAX_FIRMWARE_SIZE (1 * 1024 * 1024)
#define CNSS_MAX_FILE_NAME 20
#define PINCTRL_SLEEP 0
#define PINCTRL_ACTIVE 1
enum cnss_bus_width_type {
CNSS_BUS_WIDTH_NONE,
CNSS_BUS_WIDTH_LOW,
CNSS_BUS_WIDTH_MEDIUM,
CNSS_BUS_WIDTH_HIGH
};
enum cnss_cc_src {
CNSS_SOURCE_CORE,
CNSS_SOURCE_11D,
CNSS_SOURCE_USER
};
/* FW image files */
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_wlan_runtime_ops {
int (*runtime_suspend)(struct pci_dev *pdev);
int (*runtime_resume)(struct pci_dev *pdev);
};
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 (*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);
void (*modem_status)(struct pci_dev *pdev, int state);
void (*update_status)(struct pci_dev *pdev, uint32_t status);
struct cnss_wlan_runtime_ops *runtime_ops;
const struct pci_device_id *id_table;
};
/*
* codeseg_total_bytes: Total bytes across all the codesegment blocks
* num_codesegs: No of Pages used
* codeseg_size: Size of each segment. Should be power of 2 and multiple of 4K
* codeseg_size_log2: log2(codeseg_size)
* codeseg_busaddr: Physical address of the DMAble memory;4K aligned
*/
#define CODESWAP_MAX_CODESEGS 16
struct codeswap_codeseg_info {
u32 codeseg_total_bytes;
u32 num_codesegs;
u32 codeseg_size;
u32 codeseg_size_log2;
void *codeseg_busaddr[CODESWAP_MAX_CODESEGS];
};
struct image_desc_info {
dma_addr_t fw_addr;
u32 fw_size;
dma_addr_t bdata_addr;
u32 bdata_size;
};
/* platform capabilities */
enum cnss_platform_cap_flag {
CNSS_HAS_EXTERNAL_SWREG = 0x01,
CNSS_HAS_UART_ACCESS = 0x02,
};
struct cnss_platform_cap {
u32 cap_flag;
};
/* WLAN driver status, keep it aligned with cnss2 */
enum cnss_driver_status {
CNSS_UNINITIALIZED,
CNSS_INITIALIZED,
CNSS_LOAD_UNLOAD,
CNSS_RECOVERY,
CNSS_FW_DOWN,
CNSS_SSR_FAIL,
};
enum cnss_runtime_request {
CNSS_PM_RUNTIME_GET,
CNSS_PM_RUNTIME_PUT,
CNSS_PM_RUNTIME_MARK_LAST_BUSY,
CNSS_PM_RUNTIME_RESUME,
CNSS_PM_RUNTIME_PUT_NOIDLE,
CNSS_PM_REQUEST_RESUME,
CNSS_PM_RUNTIME_PUT_AUTO,
CNSS_PM_GET_NORESUME,
};
struct dma_iommu_mapping *cnss_smmu_get_mapping(void);
int cnss_smmu_map(phys_addr_t paddr, uint32_t *iova_addr, size_t size);
int cnss_get_fw_image(struct image_desc_info *image_desc_info);
void cnss_runtime_init(struct device *dev, int auto_delay);
void cnss_runtime_exit(struct device *dev);
void cnss_wlan_pci_link_down(void);
int cnss_pcie_shadow_control(struct pci_dev *dev, bool enable);
int cnss_wlan_register_driver(struct cnss_wlan_driver *driver);
void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver);
int cnss_get_fw_files(struct cnss_fw_files *pfw_files);
int cnss_get_fw_files_for_target(struct cnss_fw_files *pfw_files,
u32 target_type, u32 target_version);
void cnss_get_qca9377_fw_files(struct cnss_fw_files *pfw_files,
u32 size, u32 tufello_dual_fw);
int cnss_request_bus_bandwidth(int bandwidth);
#ifdef CONFIG_CNSS_SECURE_FW
int cnss_get_sha_hash(const u8 *data, u32 data_len,
u8 *hash_idx, u8 *out);
void *cnss_get_fw_ptr(void);
#endif
int cnss_get_codeswap_struct(struct codeswap_codeseg_info *swap_seg);
int cnss_get_bmi_setup(void);
#ifdef CONFIG_PCI_MSM
int cnss_wlan_pm_control(bool vote);
#endif
void cnss_lock_pm_sem(void);
void cnss_release_pm_sem(void);
void cnss_request_pm_qos_type(int latency_type, u32 qos_val);
void cnss_request_pm_qos(u32 qos_val);
void cnss_remove_pm_qos(void);
void cnss_pci_request_pm_qos_type(int latency_type, u32 qos_val);
void cnss_pci_request_pm_qos(u32 qos_val);
void cnss_pci_remove_pm_qos(void);
void cnss_sdio_request_pm_qos_type(int latency_type, u32 qos_val);
void cnss_sdio_request_pm_qos(u32 qos_val);
void cnss_sdio_remove_pm_qos(void);
int cnss_get_platform_cap(struct cnss_platform_cap *cap);
void cnss_set_driver_status(enum cnss_driver_status driver_status);
#ifndef CONFIG_WCNSS_MEM_PRE_ALLOC
static inline int wcnss_pre_alloc_reset(void) { return 0; }
#endif
int msm_pcie_enumerate(u32 rc_idx);
int cnss_auto_suspend(void);
int cnss_auto_resume(void);
int cnss_prevent_auto_suspend(const char *caller_func);
int cnss_allow_auto_suspend(const char *caller_func);
int cnss_is_auto_suspend_allowed(const char *caller_func);
int cnss_pm_runtime_request(struct device *dev, enum
cnss_runtime_request request);
void cnss_set_cc_source(enum cnss_cc_src cc_source);
enum cnss_cc_src cnss_get_cc_source(void);
#endif
void cnss_pm_wake_lock_init(struct wakeup_source **ws, const char *name);
void cnss_pm_wake_lock(struct wakeup_source *ws);
void cnss_device_crashed(void);
void cnss_device_self_recovery(void);
void *cnss_get_virt_ramdump_mem(unsigned long *size);
void cnss_schedule_recovery_work(void);
int cnss_pcie_set_wlan_mac_address(const u8 *in, uint32_t len);
u8 *cnss_get_wlan_mac_address(struct device *dev, uint32_t *num);
int cnss_sdio_set_wlan_mac_address(const u8 *in, uint32_t len);
enum {
CNSS_RESET_SOC = 0,
CNSS_RESET_SUBSYS_COUPLED,
CNSS_RESET_LEVEL_MAX
};
int cnss_get_restart_level(void);
struct cnss_sdio_wlan_driver {
const char *name;
const struct sdio_device_id *id_table;
int (*probe)(struct sdio_func *func, const struct sdio_device_id *id);
void (*remove)(struct sdio_func *func);
int (*reinit)(struct sdio_func *func, const struct sdio_device_id *id);
void (*shutdown)(struct sdio_func *func);
void (*crash_shutdown)(struct sdio_func *func);
int (*suspend)(struct device *dev);
int (*resume)(struct device *dev);
};
int cnss_sdio_wlan_register_driver(struct cnss_sdio_wlan_driver *driver);
void cnss_sdio_wlan_unregister_driver(struct cnss_sdio_wlan_driver *driver);
typedef void (*oob_irq_handler_t)(void *dev_para);
int cnss_wlan_query_oob_status(void);
int cnss_wlan_register_oob_irq_handler(oob_irq_handler_t handler, void *pm_oob);
int cnss_wlan_unregister_oob_irq_handler(void *pm_oob);
void cnss_dump_stack(struct task_struct *task);
u8 *cnss_common_get_wlan_mac_address(struct device *dev, uint32_t *num);
void cnss_init_work(struct work_struct *work, work_func_t func);
void cnss_flush_delayed_work(void *dwork);
void cnss_flush_work(void *work);
void cnss_pm_wake_lock_timeout(struct wakeup_source *ws, ulong msec);
void cnss_pm_wake_lock_release(struct wakeup_source *ws);
void cnss_pm_wake_lock_destroy(struct wakeup_source *ws);
void cnss_get_monotonic_boottime(struct timespec64 *ts);
void cnss_get_boottime(struct timespec *ts);
void cnss_init_delayed_work(struct delayed_work *work, work_func_t func);
int cnss_vendor_cmd_reply(struct sk_buff *skb);
int cnss_set_cpus_allowed_ptr(struct task_struct *task, ulong cpu);
int cnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count);
int cnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 *ch_count, u16 buf_len);
int cnss_wlan_set_dfs_nol(const void *info, u16 info_len);
int cnss_wlan_get_dfs_nol(void *info, u16 info_len);
int cnss_common_request_bus_bandwidth(struct device *dev, int bandwidth);
void cnss_common_device_crashed(struct device *dev);
void cnss_common_device_self_recovery(struct device *dev);
void *cnss_common_get_virt_ramdump_mem(struct device *dev, unsigned long *size);
void cnss_common_schedule_recovery_work(struct device *dev);
int cnss_common_set_wlan_mac_address(struct device *dev, const u8 *in, uint32_t len);
u8 *cnss_common_get_wlan_mac_address(struct device *dev, uint32_t *num);
int cnss_power_up(struct device *dev);
int cnss_power_down(struct device *dev);
int cnss_sdio_configure_spdt(bool state);
int cnss_common_register_tsf_captured_handler(struct device *dev, irq_handler_t handler,
void *ctx);
int cnss_common_unregister_tsf_captured_handler(struct device *dev, void *ctx);
#endif /* _NET_CNSS_H_ */

56
include/net/cnss_logger.h Normal file
View file

@ -0,0 +1,56 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2016,2021, The Linux Foundation. All rights reserved. */
#ifndef _NET_CNSS_LOGGER_H_
#define _NET_CNSS_LOGGER_H_
struct sk_buff;
struct wiphy;
#if IS_ENABLED(CONFIG_CNSS_LOGGER)
int cnss_logger_event_register(int radio, int event,
int (*cb)(struct sk_buff *skb));
int cnss_logger_event_unregister(int radio, int event,
int (*cb)(struct sk_buff *skb));
int cnss_logger_device_register(struct wiphy *wiphy, const char *name);
int cnss_logger_device_unregister(int radio, struct wiphy *wiphy);
int cnss_logger_nl_ucast(struct sk_buff *skb, int portid, int flag);
int cnss_logger_nl_bcast(struct sk_buff *skb, int portid, int flag);
#else
static inline int cnss_logger_event_register(int radio, int event,
int (*cb)(struct sk_buff *skb))
{
return 0;
}
static inline int cnss_logger_event_unregister(int radio, int event,
int (*cb)(struct sk_buff *skb))
{
return 0;
}
static inline int cnss_logger_device_register(struct wiphy *wiphy,
const char *name)
{
return 0;
}
static inline int cnss_logger_device_unregister(int radio, struct wiphy *wiphy)
{
return 0;
}
static inline int cnss_logger_nl_ucast(struct sk_buff *skb, int portid,
int flag)
{
return 0;
}
static inline int cnss_logger_nl_bcast(struct sk_buff *skb, int portid,
int flag)
{
return 0;
}
#endif /* CONFIG_CNSS_LOGGER */
#endif /* _NET_CNSS_LOGGER_H_ */

View file

@ -0,0 +1,87 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#ifndef __UAPI_ESOC_CTRL_H__
#define __UAPI_ESOC_CTRL_H__
#include <linux/types.h>
#define ESOC_CODE 0xCC
#define ESOC_CMD_EXE _IOW(ESOC_CODE, 1, unsigned int)
#define ESOC_WAIT_FOR_REQ _IOR(ESOC_CODE, 2, unsigned int)
#define ESOC_NOTIFY _IOW(ESOC_CODE, 3, unsigned int)
#define ESOC_GET_STATUS _IOR(ESOC_CODE, 4, unsigned int)
#define ESOC_GET_ERR_FATAL _IOR(ESOC_CODE, 5, unsigned int)
#define ESOC_WAIT_FOR_CRASH _IOR(ESOC_CODE, 6, unsigned int)
#define ESOC_REG_REQ_ENG _IO(ESOC_CODE, 7)
#define ESOC_REG_CMD_ENG _IO(ESOC_CODE, 8)
#define ESOC_GET_LINK_ID _IOWR(ESOC_CODE, 9, __u64)
#define ESOC_SET_BOOT_FAIL_ACT _IOW(ESOC_CODE, 10, unsigned int)
#define ESOC_SET_N_PON_TRIES _IOW(ESOC_CODE, 11, unsigned int)
#define ESOC_REQ_SEND_SHUTDOWN ESOC_REQ_SEND_SHUTDOWN
#define ESOC_REQ_CRASH_SHUTDOWN ESOC_REQ_CRASH_SHUTDOWN
#define ESOC_PON_RETRY ESOC_PON_RETRY
#define ESOC_BOOT_FAIL_ACTION
#define ESOC_LINK_ID
enum esoc_boot_fail_action {
BOOT_FAIL_ACTION_RETRY,
BOOT_FAIL_ACTION_COLD_RESET,
BOOT_FAIL_ACTION_SHUTDOWN,
BOOT_FAIL_ACTION_PANIC,
BOOT_FAIL_ACTION_NOP,
BOOT_FAIL_ACTION_S3_RESET,
BOOT_FAIL_ACTION_LAST,
};
enum esoc_evt {
ESOC_RUN_STATE = 0x1,
ESOC_UNEXPECTED_RESET,
ESOC_ERR_FATAL,
ESOC_IN_DEBUG,
ESOC_REQ_ENG_ON,
ESOC_REQ_ENG_OFF,
ESOC_CMD_ENG_ON,
ESOC_CMD_ENG_OFF,
ESOC_INVALID_STATE,
ESOC_RETRY_PON_EVT,
ESOC_BOOT_STATE,
};
enum esoc_cmd {
ESOC_PWR_ON = 1,
ESOC_PWR_OFF,
ESOC_FORCE_PWR_OFF,
ESOC_RESET,
ESOC_PREPARE_DEBUG,
ESOC_EXE_DEBUG,
ESOC_EXIT_DEBUG,
};
enum esoc_notify {
ESOC_IMG_XFER_DONE = 1,
ESOC_BOOT_DONE,
ESOC_BOOT_FAIL,
ESOC_IMG_XFER_RETRY,
ESOC_IMG_XFER_FAIL,
ESOC_UPGRADE_AVAILABLE,
ESOC_DEBUG_DONE,
ESOC_DEBUG_FAIL,
ESOC_PRIMARY_CRASH,
ESOC_PRIMARY_REBOOT,
ESOC_PON_RETRY,
};
enum esoc_req {
ESOC_REQ_IMG = 1,
ESOC_REQ_DEBUG,
ESOC_REQ_SHUTDOWN,
ESOC_REQ_SEND_SHUTDOWN,
ESOC_REQ_CRASH_SHUTDOWN,
};
#endif