Merge "cnss_utils: Add support of cnss_utils for WLAN"
This commit is contained in:
commit
a9194dae5a
8 changed files with 361 additions and 0 deletions
|
@ -333,5 +333,6 @@ source "drivers/net/wireless/cw1200/Kconfig"
|
||||||
source "drivers/net/wireless/rsi/Kconfig"
|
source "drivers/net/wireless/rsi/Kconfig"
|
||||||
source "drivers/net/wireless/cnss/Kconfig"
|
source "drivers/net/wireless/cnss/Kconfig"
|
||||||
source "drivers/net/wireless/cnss_genl/Kconfig"
|
source "drivers/net/wireless/cnss_genl/Kconfig"
|
||||||
|
source "drivers/net/wireless/cnss_utils/Kconfig"
|
||||||
|
|
||||||
endif # WLAN
|
endif # WLAN
|
||||||
|
|
|
@ -67,3 +67,4 @@ obj-$(CONFIG_CNSS) += cnss/
|
||||||
obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += cnss_prealloc/
|
obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += cnss_prealloc/
|
||||||
obj-$(CONFIG_CNSS_CRYPTO) += cnss_crypto/
|
obj-$(CONFIG_CNSS_CRYPTO) += cnss_crypto/
|
||||||
obj-$(CONFIG_CNSS_GENL) += cnss_genl/
|
obj-$(CONFIG_CNSS_GENL) += cnss_genl/
|
||||||
|
obj-$(CONFIG_CNSS_UTILS) += cnss_utils/
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
config CNSS
|
config CNSS
|
||||||
tristate "CNSS driver for wifi module"
|
tristate "CNSS driver for wifi module"
|
||||||
|
select CNSS_UTILS
|
||||||
select CRYPTO
|
select CRYPTO
|
||||||
select CRYPTO_HASH
|
select CRYPTO_HASH
|
||||||
select CRYPTO_BLKCIPHER
|
select CRYPTO_BLKCIPHER
|
||||||
|
|
6
drivers/net/wireless/cnss_utils/Kconfig
Normal file
6
drivers/net/wireless/cnss_utils/Kconfig
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
config CNSS_UTILS
|
||||||
|
bool "CNSS utilities support"
|
||||||
|
---help---
|
||||||
|
Add CNSS utilities support for the WLAN driver module.
|
||||||
|
This feature enable wlan driver to use CNSS utilities APIs to set
|
||||||
|
and get wlan related information.
|
1
drivers/net/wireless/cnss_utils/Makefile
Normal file
1
drivers/net/wireless/cnss_utils/Makefile
Normal file
|
@ -0,0 +1 @@
|
||||||
|
obj-$(CONFIG_CNSS_UTILS) += cnss_utils.o
|
310
drivers/net/wireless/cnss_utils/cnss_utils.c
Normal file
310
drivers/net/wireless/cnss_utils/cnss_utils.c
Normal file
|
@ -0,0 +1,310 @@
|
||||||
|
/* Copyright (c) 2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) "cnss_utils: " fmt
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <net/cnss_utils.h>
|
||||||
|
|
||||||
|
#define CNSS_MAX_CH_NUM 45
|
||||||
|
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
|
||||||
|
struct cnss_wlan_mac_addr {
|
||||||
|
u8 mac_addr[MAX_NO_OF_MAC_ADDR][ETH_ALEN];
|
||||||
|
u32 no_of_mac_addr_set;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
bool is_wlan_mac_set;
|
||||||
|
struct cnss_wlan_mac_addr wlan_mac_addr;
|
||||||
|
enum cnss_utils_cc_src cc_source;
|
||||||
|
} *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 = kmalloc(info_len, GFP_ATOMIC);
|
||||||
|
if (!temp)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
memcpy(temp, info, info_len);
|
||||||
|
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);
|
||||||
|
|
||||||
|
int cnss_utils_set_wlan_mac_address(const u8 *in, const uint32_t len)
|
||||||
|
{
|
||||||
|
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 (priv->is_wlan_mac_set) {
|
||||||
|
pr_debug("WLAN MAC address is already set\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->is_wlan_mac_set = true;
|
||||||
|
addr = &priv->wlan_mac_addr;
|
||||||
|
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, in += ETH_ALEN) {
|
||||||
|
ether_addr_copy(temp, in);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(cnss_utils_set_wlan_mac_address);
|
||||||
|
|
||||||
|
u8 *cnss_utils_get_wlan_mac_address(struct device *dev, uint32_t *num)
|
||||||
|
{
|
||||||
|
struct cnss_utils_priv *priv = cnss_utils_priv;
|
||||||
|
struct cnss_wlan_mac_addr *addr = NULL;
|
||||||
|
|
||||||
|
if (!priv)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!priv->is_wlan_mac_set) {
|
||||||
|
pr_debug("WLAN MAC address is not set\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = &priv->wlan_mac_addr;
|
||||||
|
*num = addr->no_of_mac_addr_set;
|
||||||
|
return &addr->mac_addr[0][0];
|
||||||
|
out:
|
||||||
|
*num = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(cnss_utils_get_wlan_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 int __init cnss_utils_init(void)
|
||||||
|
{
|
||||||
|
struct cnss_utils_priv *priv = NULL;
|
||||||
|
|
||||||
|
priv = kmalloc(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_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(DEVICE "CNSS Utilities Driver");
|
|
@ -468,6 +468,7 @@ config MINIDUMP_MAX_ENTRIES
|
||||||
|
|
||||||
config ICNSS
|
config ICNSS
|
||||||
tristate "Platform driver for Q6 integrated connectivity"
|
tristate "Platform driver for Q6 integrated connectivity"
|
||||||
|
select CNSS_UTILS
|
||||||
---help---
|
---help---
|
||||||
This module adds support for Q6 integrated WLAN connectivity
|
This module adds support for Q6 integrated WLAN connectivity
|
||||||
subsystem. This module is responsible for communicating WLAN on/off
|
subsystem. This module is responsible for communicating WLAN on/off
|
||||||
|
|
40
include/net/cnss_utils.h
Normal file
40
include/net/cnss_utils.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/* Copyright (c) 2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CNSS_UTILS_H_
|
||||||
|
#define _CNSS_UTILS_H_
|
||||||
|
|
||||||
|
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 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
|
Loading…
Add table
Reference in a new issue