Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b56fde2f authored by hangtian's avatar hangtian
Browse files

cnss: Add cnss driver to msm-4.14



This is the snapshot of the cnss driver from msm-4.9 commit 7524a2.

Change-Id: I1d45b978d6302c28f32777f5a80e313464c0a47a
CRs-Fixed: 2487159
Signed-off-by: default avatarhangtian <hangtian@codeaurora.org>
parent b6fbaa1d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -136,6 +136,7 @@ config CLD_LL_CORE
	  support.

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"

+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o

obj-$(CONFIG_CNSS2) += cnss2/

obj-$(CONFIG_CNSS)              += cnss/
obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += cnss_prealloc/
obj-$(CONFIG_CNSS_UTILS) += cnss_utils/
obj-$(CONFIG_CNSS_GENL) += cnss_genl/
+129 −0
Original line number Diff line number Diff line
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.
+6 −0
Original line number Diff line number Diff line
# 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/
+450 −0
Original line number Diff line number Diff line
/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#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 = kmalloc(info_len, GFP_KERNEL);
	if (!temp) {
		mutex_unlock(&dfs_nol_info_lock);
		return -ENOMEM;
	}

	memcpy(temp, info, info_len);
	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)
{
	wakeup_source_init(ws, 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_trash(ws);
}
EXPORT_SYMBOL(cnss_pm_wake_lock_destroy);

void cnss_get_monotonic_boottime(struct timespec *ts)
{
	get_monotonic_boottime(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", __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);
Loading