mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
qcacmn: Add core\utils directory and files to qcacmn
As a part of UMAC convergence, move the core\utils logging to qcacmn. CRs-Fixed: 1109855 Change-Id: I499a392f74f3e52e99df4d03e4a27bce6cf5be7c
This commit is contained in:
parent
6195152790
commit
60644c29e6
30 changed files with 15592 additions and 0 deletions
200
utils/nlink/inc/wlan_nlink_common.h
Normal file
200
utils/nlink/inc/wlan_nlink_common.h
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||
*
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
* above copyright notice and this permission notice appear in all
|
||||
* copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||
* under proprietary terms before Copyright ownership was assigned
|
||||
* to the Linux Foundation.
|
||||
*/
|
||||
|
||||
/*===========================================================================
|
||||
\file wlan_nlink_common.h
|
||||
|
||||
Exports and types for the Netlink Service interface. This header file contains
|
||||
message types and definitions that is shared between the user space service
|
||||
(e.g. logging service) and WLAN kernel module.
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
#ifndef WLAN_NLINK_COMMON_H__
|
||||
#define WLAN_NLINK_COMMON_H__
|
||||
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* External Functions
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Preprocessor Definitions and Constants
|
||||
*-------------------------------------------------------------------------*/
|
||||
#define WLAN_NL_MAX_PAYLOAD 256 /* maximum size for netlink message */
|
||||
#define WLAN_NLINK_PROTO_FAMILY NETLINK_USERSOCK
|
||||
#define WLAN_NLINK_MCAST_GRP_ID 0x01
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Type Declarations
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The following enum defines the target service within WLAN driver for which the
|
||||
* message is intended for. Each service along with its counterpart
|
||||
* in the user space, define a set of messages they recognize.
|
||||
* Each of this message will have an header of type tAniMsgHdr defined below.
|
||||
* Each Netlink message to/from a kernel module will contain only one
|
||||
* message which is preceded by a tAniMsgHdr. The maximun size (in bytes) of
|
||||
* a netlink message is assumed to be MAX_PAYLOAD bytes.
|
||||
*
|
||||
* +------------+-------+----------+----------+
|
||||
* |Netlink hdr | Align |tAniMsgHdr| msg body |
|
||||
* +------------+-------+----------|----------+
|
||||
*/
|
||||
|
||||
/* Message Types */
|
||||
#define WLAN_SVC_FW_CRASHED_IND 0x100
|
||||
#define WLAN_SVC_LTE_COEX_IND 0x101
|
||||
#define WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND 0x102
|
||||
#define WLAN_SVC_DFS_CAC_START_IND 0x103
|
||||
#define WLAN_SVC_DFS_CAC_END_IND 0x104
|
||||
#define WLAN_SVC_DFS_RADAR_DETECT_IND 0x105
|
||||
#define WLAN_SVC_WLAN_STATUS_IND 0x106
|
||||
#define WLAN_SVC_WLAN_VERSION_IND 0x107
|
||||
#define WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND 0x108
|
||||
#define WLAN_SVC_WLAN_TP_IND 0x109
|
||||
#define WLAN_SVC_RPS_ENABLE_IND 0x10A
|
||||
#define WLAN_SVC_WLAN_TP_TX_IND 0x10B
|
||||
#define WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND 0x10C
|
||||
#define WLAN_SVC_WLAN_RADIO_INDEX 0x10D
|
||||
#define WLAN_SVC_FW_SHUTDOWN_IND 0x10E
|
||||
#define WLAN_SVC_MAX_SSID_LEN 32
|
||||
#define WLAN_SVC_MAX_BSSID_LEN 6
|
||||
#define WLAN_SVC_MAX_STR_LEN 16
|
||||
#define WLAN_SVC_MAX_NUM_CHAN 128
|
||||
#define WLAN_SVC_COUNTRY_CODE_LEN 3
|
||||
|
||||
#define ANI_NL_MSG_BASE 0x10 /* Some arbitrary base */
|
||||
|
||||
typedef enum eAniNlModuleTypes {
|
||||
ANI_NL_MSG_PUMAC = ANI_NL_MSG_BASE + 0x01, /* PTT Socket App */
|
||||
ANI_NL_MSG_PTT = ANI_NL_MSG_BASE + 0x07, /* Quarky GUI */
|
||||
WLAN_NL_MSG_OEM = ANI_NL_MSG_BASE + 0x09,
|
||||
WLAN_NL_MSG_SVC,
|
||||
WLAN_NL_MSG_CNSS_DIAG = ANI_NL_MSG_BASE + 0x0B, /* Value needs to be 27 */
|
||||
ANI_NL_MSG_LOG,
|
||||
ANI_NL_MSG_MAX
|
||||
} tAniNlModTypes, tWlanNlModTypes;
|
||||
|
||||
#define WLAN_NL_MSG_BASE ANI_NL_MSG_BASE
|
||||
#define WLAN_NL_MSG_MAX ANI_NL_MSG_MAX
|
||||
|
||||
/* All Netlink messages must contain this header */
|
||||
typedef struct sAniHdr {
|
||||
unsigned short type;
|
||||
unsigned short length;
|
||||
} tAniHdr, tAniMsgHdr;
|
||||
|
||||
typedef struct sAniNlMsg {
|
||||
struct nlmsghdr nlh; /* Netlink Header */
|
||||
int radio; /* unit number of the radio */
|
||||
tAniHdr wmsg; /* Airgo Message Header */
|
||||
} tAniNlHdr;
|
||||
|
||||
struct radio_index_tlv {
|
||||
unsigned short type;
|
||||
unsigned short length;
|
||||
int radio;
|
||||
};
|
||||
|
||||
struct wlan_status_data {
|
||||
uint8_t lpss_support;
|
||||
uint8_t is_on;
|
||||
uint8_t vdev_id;
|
||||
uint8_t is_connected;
|
||||
int8_t rssi;
|
||||
uint8_t ssid_len;
|
||||
uint8_t country_code[WLAN_SVC_COUNTRY_CODE_LEN];
|
||||
uint32_t vdev_mode;
|
||||
uint32_t freq;
|
||||
uint32_t numChannels;
|
||||
uint8_t channel_list[WLAN_SVC_MAX_NUM_CHAN];
|
||||
uint8_t ssid[WLAN_SVC_MAX_SSID_LEN];
|
||||
uint8_t bssid[WLAN_SVC_MAX_BSSID_LEN];
|
||||
};
|
||||
|
||||
struct wlan_version_data {
|
||||
uint32_t chip_id;
|
||||
char chip_name[WLAN_SVC_MAX_STR_LEN];
|
||||
char chip_from[WLAN_SVC_MAX_STR_LEN];
|
||||
char host_version[WLAN_SVC_MAX_STR_LEN];
|
||||
char fw_version[WLAN_SVC_MAX_STR_LEN];
|
||||
};
|
||||
|
||||
struct wlan_dfs_info {
|
||||
uint16_t channel;
|
||||
uint8_t country_code[WLAN_SVC_COUNTRY_CODE_LEN];
|
||||
};
|
||||
|
||||
/*
|
||||
* Maximim number of queues supported by WLAN driver. Setting an upper
|
||||
* limit. Actual number of queues may be smaller than this value.
|
||||
*/
|
||||
#define WLAN_SVC_IFACE_NUM_QUEUES 6
|
||||
|
||||
/**
|
||||
* struct wlan_rps_data - structure to send RPS info to cnss-daemon
|
||||
* @ifname: interface name for which the RPS data belongs to
|
||||
* @num_queues: number of rx queues for which RPS data is being sent
|
||||
* @cpu_map_list: array of cpu maps for different rx queues supported by
|
||||
* the wlan driver
|
||||
*
|
||||
* The structure specifies the format of data exchanged between wlan
|
||||
* driver and cnss-daemon. On receipt of the data, cnss-daemon is expected
|
||||
* to apply the 'cpu_map' for each rx queue belonging to the interface 'ifname'
|
||||
*/
|
||||
struct wlan_rps_data {
|
||||
char ifname[IFNAMSIZ];
|
||||
uint16_t num_queues;
|
||||
uint16_t cpu_map_list[WLAN_SVC_IFACE_NUM_QUEUES];
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wlan_tp_level - indicates wlan throughput level
|
||||
* @WLAN_SVC_TP_NONE: used for initialization
|
||||
* @WLAN_SVC_TP_LOW: used to identify low throughput level
|
||||
* @WLAN_SVC_TP_MEDIUM: used to identify medium throughput level
|
||||
* @WLAN_SVC_TP_HIGH: used to identify high throughput level
|
||||
*
|
||||
* The different throughput levels are determined on the basis of # of tx and
|
||||
* rx packets and other threshold values. For example, if the # of total
|
||||
* packets sent or received by the driver is greater than 500 in the last 100ms
|
||||
* , the driver has a high throughput requirement. The driver may tweak certain
|
||||
* system parameters based on the throughput level.
|
||||
*/
|
||||
enum wlan_tp_level {
|
||||
WLAN_SVC_TP_NONE,
|
||||
WLAN_SVC_TP_LOW,
|
||||
WLAN_SVC_TP_MEDIUM,
|
||||
WLAN_SVC_TP_HIGH,
|
||||
};
|
||||
|
||||
#endif /* WLAN_NLINK_COMMON_H__ */
|
||||
60
utils/nlink/inc/wlan_nlink_srv.h
Normal file
60
utils/nlink/inc/wlan_nlink_srv.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||
*
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
* above copyright notice and this permission notice appear in all
|
||||
* copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||
* under proprietary terms before Copyright ownership was assigned
|
||||
* to the Linux Foundation.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* wlan_nlink_srv.h
|
||||
*
|
||||
* wlan_nlink_srv is used to RX/TX Netlink messages from user space to kernel
|
||||
* modules and vice versa. Kernel modules must register a message handler for a
|
||||
* message type so that the wlan_nlink_srv can invoke the corresponding msg handler
|
||||
* whenever a Netlink message of a particular type has been received from an
|
||||
* application. In the opposite direction, wlan_nlink_srv provides a mechanism
|
||||
* which kernel modules can use to send Netlink messages to applications.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef WLAN_NLINK_SRV_H
|
||||
#define WLAN_NLINK_SRV_H
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/netlink.h>
|
||||
#include <wlan_nlink_common.h>
|
||||
|
||||
#define INVALID_PID -1
|
||||
#define NLINK_MAX_CALLBACKS (WLAN_NL_MSG_MAX - WLAN_NL_MSG_BASE)
|
||||
|
||||
typedef int (*nl_srv_msg_callback)(struct sk_buff *skb);
|
||||
|
||||
int nl_srv_init(void *wiphy);
|
||||
void nl_srv_exit(void);
|
||||
int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler);
|
||||
int nl_srv_unregister(tWlanNlModTypes msg_type,
|
||||
nl_srv_msg_callback msg_handler);
|
||||
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag);
|
||||
int nl_srv_bcast(struct sk_buff *skb);
|
||||
int nl_srv_is_initialized(void);
|
||||
#endif
|
||||
539
utils/nlink/src/wlan_nlink_srv.c
Normal file
539
utils/nlink/src/wlan_nlink_srv.c
Normal file
|
|
@ -0,0 +1,539 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||
*
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
* above copyright notice and this permission notice appear in all
|
||||
* copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||
* under proprietary terms before Copyright ownership was assigned
|
||||
* to the Linux Foundation.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* wlan_nlink_srv.c
|
||||
*
|
||||
* This file contains the definitions specific to the wlan_nlink_srv
|
||||
*
|
||||
******************************************************************************/
|
||||
/*
|
||||
* If MULTI_IF_NAME is not defined, then this is the primary instance of the
|
||||
* driver and the diagnostics netlink socket will be available. If
|
||||
* MULTI_IF_NAME is defined then this is not the primary instance of the driver
|
||||
* and the diagnotics netlink socket will not be available since this
|
||||
* diagnostics netlink socket can only be exposed by one instance of the driver.
|
||||
*/
|
||||
#ifndef MULTI_IF_NAME
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/sock.h>
|
||||
#include <wlan_nlink_srv.h>
|
||||
#include <qdf_trace.h>
|
||||
|
||||
#if defined(CONFIG_CNSS_LOGGER)
|
||||
|
||||
#include <net/cnss_logger.h>
|
||||
|
||||
static int radio_idx = -EINVAL;
|
||||
static void *wiphy_ptr;
|
||||
static bool logger_initialized;
|
||||
|
||||
/**
|
||||
* nl_srv_init() - wrapper function to register to cnss_logger
|
||||
* @wiphy: the pointer to the wiphy structure
|
||||
*
|
||||
* The netlink socket is no longer initialized in the driver itself, instead
|
||||
* will be initialized in the cnss_logger module, the driver should register
|
||||
* itself to cnss_logger module to get the radio_index for all the netlink
|
||||
* operation. (cfg80211 vendor command is using different netlink socket).
|
||||
*
|
||||
* The cnss_logger_device_register() use to register the driver with the
|
||||
* wiphy structure and the module name (debug purpose) and then return the
|
||||
* radio_index depending on the availibility.
|
||||
*
|
||||
* Return: radio index for success and -EINVAL for failure
|
||||
*/
|
||||
int nl_srv_init(void *wiphy)
|
||||
{
|
||||
if (logger_initialized)
|
||||
goto initialized;
|
||||
|
||||
wiphy_ptr = wiphy;
|
||||
radio_idx = cnss_logger_device_register(wiphy, THIS_MODULE->name);
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: radio_index: %d, wiphy_ptr: %p",
|
||||
__func__, radio_idx, wiphy_ptr);
|
||||
|
||||
if (radio_idx >= 0)
|
||||
logger_initialized = true;
|
||||
|
||||
initialized:
|
||||
return radio_idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_exit() - wrapper function to unregister from cnss_logger
|
||||
*
|
||||
* The cnss_logger_device_unregister() use to unregister the driver with
|
||||
* the radio_index assigned and wiphy structure from cnss_logger.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void nl_srv_exit(void)
|
||||
{
|
||||
if (logger_initialized) {
|
||||
cnss_logger_device_unregister(radio_idx, wiphy_ptr);
|
||||
radio_idx = -EINVAL;
|
||||
wiphy_ptr = NULL;
|
||||
logger_initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_ucast() - wrapper function to do unicast tx through cnss_logger
|
||||
* @skb: the socket buffer to send
|
||||
* @dst_pid: the port id
|
||||
* @flag: the blocking or nonblocking flag
|
||||
*
|
||||
* The nl_srv_is_initialized() is used to do sanity check if the netlink
|
||||
* service is ready, e.g if the radio_index is assigned properly, if not
|
||||
* the driver should take the responsibility to free the skb.
|
||||
*
|
||||
* The cnss_logger_nl_ucast() use the same parameters to send the socket
|
||||
* buffers.
|
||||
*
|
||||
* Return: the error of the transmission status
|
||||
*/
|
||||
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
|
||||
/* sender's pid */
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
|
||||
NETLINK_CB(skb).pid = 0;
|
||||
#else
|
||||
NETLINK_CB(skb).portid = 0;
|
||||
#endif
|
||||
/* not multicast */
|
||||
NETLINK_CB(skb).dst_group = 0;
|
||||
|
||||
if (nl_srv_is_initialized() == 0)
|
||||
err = cnss_logger_nl_ucast(skb, dst_pid, flag);
|
||||
else
|
||||
dev_kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_bcast() - wrapper function to do broadcast tx through cnss_logger
|
||||
* @skb: the socket buffer to send
|
||||
*
|
||||
* The cnss_logger_nl_bcast() is used to transmit the socket buffer.
|
||||
*
|
||||
* Return: status of transmission
|
||||
*/
|
||||
int nl_srv_bcast(struct sk_buff *skb)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
int flags = GFP_KERNEL;
|
||||
|
||||
if (in_interrupt() || irqs_disabled() || in_atomic())
|
||||
flags = GFP_ATOMIC;
|
||||
|
||||
/* sender's pid */
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
|
||||
NETLINK_CB(skb).pid = 0;
|
||||
#else
|
||||
NETLINK_CB(skb).portid = 0;
|
||||
#endif
|
||||
/* destination group */
|
||||
NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID;
|
||||
|
||||
if (nl_srv_is_initialized() == 0)
|
||||
err = cnss_logger_nl_bcast(skb, WLAN_NLINK_MCAST_GRP_ID, flags);
|
||||
else
|
||||
dev_kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_unregister() - wrapper function to unregister event to cnss_logger
|
||||
* @msg_type: the message to unregister
|
||||
* @msg_handler: the message handler
|
||||
*
|
||||
* The cnss_logger_event_unregister() is used to unregister the message and
|
||||
* message handler.
|
||||
*
|
||||
* Return: 0 if successfully unregister, otherwise proper error code
|
||||
*/
|
||||
int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (nl_srv_is_initialized() != 0)
|
||||
return ret;
|
||||
|
||||
if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
|
||||
msg_handler != NULL) {
|
||||
ret = cnss_logger_event_unregister(radio_idx, msg_type,
|
||||
msg_handler);
|
||||
} else {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"NLINK: nl_srv_unregister failed for msg_type %d",
|
||||
msg_type);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_register() - wrapper function to register event to cnss_logger
|
||||
* @msg_type: the message to register
|
||||
* @msg_handler: the message handler
|
||||
*
|
||||
* The cnss_logger_event_register() is used to register the message and
|
||||
* message handler.
|
||||
*
|
||||
* Return: 0 if successfully register, otherwise proper error code
|
||||
*/
|
||||
int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (nl_srv_is_initialized() != 0)
|
||||
return ret;
|
||||
|
||||
if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
|
||||
msg_handler != NULL) {
|
||||
ret = cnss_logger_event_register(radio_idx, msg_type,
|
||||
msg_handler);
|
||||
} else {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"NLINK: nl_srv_register failed for msg_type %d",
|
||||
msg_type);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_is_initialized() - check if netlink service is initialized
|
||||
*
|
||||
* Return: 0 if it is initialized, otherwise error code
|
||||
*/
|
||||
inline int nl_srv_is_initialized(void)
|
||||
{
|
||||
if (logger_initialized)
|
||||
return 0;
|
||||
else
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
||||
/* Global variables */
|
||||
static DEFINE_MUTEX(nl_srv_sem);
|
||||
static struct sock *nl_srv_sock;
|
||||
static nl_srv_msg_callback nl_srv_msg_handler[NLINK_MAX_CALLBACKS];
|
||||
|
||||
/* Forward declaration */
|
||||
static void nl_srv_rcv(struct sk_buff *sk);
|
||||
static void nl_srv_rcv_skb(struct sk_buff *skb);
|
||||
static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh);
|
||||
|
||||
/*
|
||||
* Initialize the netlink service.
|
||||
* Netlink service is usable after this.
|
||||
*/
|
||||
int nl_srv_init(void *wiphy)
|
||||
{
|
||||
int retcode = 0;
|
||||
struct netlink_kernel_cfg cfg = {
|
||||
.groups = WLAN_NLINK_MCAST_GRP_ID,
|
||||
.input = nl_srv_rcv
|
||||
};
|
||||
|
||||
nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_PROTO_FAMILY,
|
||||
&cfg);
|
||||
|
||||
if (nl_srv_sock != NULL) {
|
||||
memset(nl_srv_msg_handler, 0, sizeof(nl_srv_msg_handler));
|
||||
} else {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"NLINK: netlink_kernel_create failed");
|
||||
retcode = -ECONNREFUSED;
|
||||
}
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deinit the netlink service.
|
||||
* Netlink service is unusable after this.
|
||||
*/
|
||||
void nl_srv_exit(void)
|
||||
{
|
||||
if (nl_srv_is_initialized() == 0)
|
||||
netlink_kernel_release(nl_srv_sock);
|
||||
|
||||
nl_srv_sock = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a message handler for a specified module.
|
||||
* Each module (e.g. WLAN_NL_MSG_BTC )will register a
|
||||
* handler to handle messages addressed to it.
|
||||
*/
|
||||
int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
int retcode = 0;
|
||||
|
||||
if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
|
||||
msg_handler != NULL) {
|
||||
nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = msg_handler;
|
||||
} else {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: nl_srv_register failed for msg_type %d",
|
||||
msg_type);
|
||||
retcode = -EINVAL;
|
||||
}
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unregister the message handler for a specified module.
|
||||
*/
|
||||
int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
int retcode = 0;
|
||||
|
||||
if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
|
||||
(nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] == msg_handler)) {
|
||||
nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = NULL;
|
||||
} else {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: nl_srv_unregister failed for msg_type %d",
|
||||
msg_type);
|
||||
retcode = -EINVAL;
|
||||
}
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unicast the message to the process in user space identfied
|
||||
* by the dst-pid
|
||||
*/
|
||||
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
NETLINK_CB(skb).portid = 0; /* sender's pid */
|
||||
NETLINK_CB(skb).dst_group = 0; /* not multicast */
|
||||
|
||||
if (nl_srv_sock)
|
||||
err = netlink_unicast(nl_srv_sock, skb, dst_pid, flag);
|
||||
|
||||
if (err < 0)
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: netlink_unicast to pid[%d] failed, ret[%d]",
|
||||
dst_pid, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Broadcast the message. Broadcast will return an error if
|
||||
* there are no listeners
|
||||
*/
|
||||
int nl_srv_bcast(struct sk_buff *skb)
|
||||
{
|
||||
int err = 0;
|
||||
int flags = GFP_KERNEL;
|
||||
|
||||
if (in_interrupt() || irqs_disabled() || in_atomic())
|
||||
flags = GFP_ATOMIC;
|
||||
|
||||
NETLINK_CB(skb).portid = 0; /* sender's pid */
|
||||
NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID; /* destination group */
|
||||
|
||||
if (nl_srv_sock)
|
||||
err = netlink_broadcast(nl_srv_sock, skb, 0,
|
||||
WLAN_NLINK_MCAST_GRP_ID, flags);
|
||||
|
||||
if ((err < 0) && (err != -ESRCH)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: netlink_broadcast failed err = %d", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Processes the Netlink socket input queue.
|
||||
* Dequeue skb's from the socket input queue and process
|
||||
* all the netlink messages in that skb, before moving
|
||||
* to the next skb.
|
||||
*/
|
||||
static void nl_srv_rcv(struct sk_buff *sk)
|
||||
{
|
||||
mutex_lock(&nl_srv_sem);
|
||||
nl_srv_rcv_skb(sk);
|
||||
mutex_unlock(&nl_srv_sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Each skb could contain multiple Netlink messages. Process all the
|
||||
* messages in one skb and discard malformed skb's silently.
|
||||
*/
|
||||
static void nl_srv_rcv_skb(struct sk_buff *skb)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
|
||||
while (skb->len >= NLMSG_SPACE(0)) {
|
||||
u32 rlen;
|
||||
|
||||
nlh = (struct nlmsghdr *)skb->data;
|
||||
|
||||
if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: Invalid "
|
||||
"Netlink message: skb[%p], len[%d], nlhdr[%p], nlmsg_len[%d]",
|
||||
skb, skb->len, nlh, nlh->nlmsg_len);
|
||||
return;
|
||||
}
|
||||
|
||||
rlen = NLMSG_ALIGN(nlh->nlmsg_len);
|
||||
if (rlen > skb->len)
|
||||
rlen = skb->len;
|
||||
nl_srv_rcv_msg(skb, nlh);
|
||||
skb_pull(skb, rlen);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a netlink message.
|
||||
* Each netlink message will have a message of type tAniMsgHdr inside.
|
||||
*/
|
||||
static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
{
|
||||
int type;
|
||||
|
||||
/* Only requests are handled by kernel now */
|
||||
if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: Received Invalid NL Req type [%x]",
|
||||
nlh->nlmsg_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
type = nlh->nlmsg_type;
|
||||
|
||||
/* Unknown message */
|
||||
if (type < WLAN_NL_MSG_BASE || type >= WLAN_NL_MSG_MAX) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: Received Invalid NL Msg type [%x]", type);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* All the messages must at least carry the tAniMsgHdr
|
||||
* Drop any message with invalid length
|
||||
*/
|
||||
if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(tAniMsgHdr))) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: Received NL Msg with invalid len[%x]",
|
||||
nlh->nlmsg_len);
|
||||
return;
|
||||
}
|
||||
|
||||
/* turn type into dispatch table offset */
|
||||
type -= WLAN_NL_MSG_BASE;
|
||||
|
||||
/* dispatch to handler */
|
||||
if (nl_srv_msg_handler[type] != NULL) {
|
||||
(nl_srv_msg_handler[type])(skb);
|
||||
} else {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: No handler for Netlink Msg [0x%X]", type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_is_initialized() - This function is used check if the netlink
|
||||
* service is initialized
|
||||
*
|
||||
* This function is used check if the netlink service is initialized
|
||||
*
|
||||
* Return: Return -EPERM if the service is not initialized
|
||||
*
|
||||
*/
|
||||
int nl_srv_is_initialized(void)
|
||||
{
|
||||
if (nl_srv_sock)
|
||||
return 0;
|
||||
|
||||
return -EPERM;
|
||||
}
|
||||
#endif
|
||||
#else /* ifndef MULTI_IF_NAME */
|
||||
|
||||
#include <wlan_nlink_srv.h>
|
||||
|
||||
int nl_srv_init(void *wiphy)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nl_srv_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_srv_bcast(struct sk_buff *skb)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_srv_is_initialized(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
Loading…
Reference in a new issue