kernel_samsung_a34x-permissive/drivers/misc/mediatek/mddp/usage/mddp_usage.c
2024-04-28 15:51:13 +02:00

244 lines
7.4 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* mddp_usage.c - Data usage API.
*
* Copyright (c) 2020 MediaTek Inc.
*/
#include <linux/types.h>
#include "mddp_ctrl.h"
#include "mddp_debug.h"
#include "mddp_dev.h"
#include "mddp_filter.h"
#include "mddp_ipc.h"
#include "mddp_usage.h"
#include "mtk_ccci_common.h"
//------------------------------------------------------------------------------
// Struct definition.
// -----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Private helper macro.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Function prototype.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Private variables.
//------------------------------------------------------------------------------
static uint32_t mddp_u_iq_trans_id_s;
static int8_t wan_id;
//------------------------------------------------------------------------------
// Private helper macro.
//------------------------------------------------------------------------------
#define MDDP_U_GET_IQ_TRANS_ID() (mddp_u_iq_trans_id_s++)
//------------------------------------------------------------------------------
// Private functions.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Public functions - WiFi Hotspot.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Public functions.
//------------------------------------------------------------------------------
void mddp_u_get_data_stats(void *buf, uint32_t *buf_len)
{
static struct mddp_u_data_stats_t cur_stats = {0};
struct mddp_u_data_stats_t *md_stats;
struct mddp_u_data_stats_t *usage;
uint32_t sm_len = 0;
md_stats = get_smem_start_addr(MD_SYS1, SMEM_USER_RAW_NETD, &sm_len);
md_stats += wan_id;
if (sm_len >= sizeof(struct mddp_u_data_stats_t)) {
usage = (struct mddp_u_data_stats_t *)buf;
*buf_len = sizeof(struct mddp_u_data_stats_t);
#define DIFF_FROM_SMEM(x) (usage->x = \
(md_stats->x > cur_stats.x) ? (md_stats->x - cur_stats.x) : 0)
DIFF_FROM_SMEM(total_tx_pkts);
DIFF_FROM_SMEM(total_tx_bytes);
DIFF_FROM_SMEM(tx_tcp_bytes);
DIFF_FROM_SMEM(tx_tcp_pkts);
DIFF_FROM_SMEM(tx_udp_bytes);
DIFF_FROM_SMEM(tx_udp_pkts);
DIFF_FROM_SMEM(tx_others_bytes);
DIFF_FROM_SMEM(tx_others_pkts);
DIFF_FROM_SMEM(total_rx_pkts);
DIFF_FROM_SMEM(total_rx_bytes);
DIFF_FROM_SMEM(rx_tcp_bytes);
DIFF_FROM_SMEM(rx_tcp_pkts);
DIFF_FROM_SMEM(rx_udp_bytes);
DIFF_FROM_SMEM(rx_udp_pkts);
DIFF_FROM_SMEM(rx_others_bytes);
DIFF_FROM_SMEM(rx_others_pkts);
memcpy(&cur_stats, md_stats, *buf_len);
} else {
MDDP_U_LOG(MDDP_LL_ERR,
"%s: Failed to copy data stats, sm_len(%d), buf_len(%d)!\n",
__func__, sm_len, *buf_len);
*buf_len = 0;
}
}
int32_t mddp_u_set_data_limit(uint8_t *buf, uint32_t buf_len)
{
uint32_t md_status;
struct mddp_md_msg_t *md_msg;
struct mddp_dev_req_set_data_limit_t *in_req;
struct mddp_u_data_limit_t limit;
int8_t id;
struct mddp_app_t *app;
if (buf_len != sizeof(struct mddp_dev_req_set_data_limit_t)) {
MDDP_U_LOG(MDDP_LL_ERR,
"%s: Invalid parameter, buf_len(%d)!\n",
__func__, buf_len);
return -EINVAL;
}
md_status = exec_ccci_kern_func_by_md_id(0, ID_GET_MD_STATE, NULL, 0);
if (md_status != MD_STATE_READY) {
MDDP_U_LOG(MDDP_LL_NOTICE,
"%s: Invalid state, md_status(%d)!\n",
__func__, md_status);
return -ENODEV;
}
md_msg = kzalloc(sizeof(struct mddp_md_msg_t) + sizeof(limit),
GFP_ATOMIC);
if (unlikely(!md_msg)) {
return -EAGAIN;
}
in_req = (struct mddp_dev_req_set_data_limit_t *)buf;
id = mddp_f_data_usage_wan_dev_name_to_id(in_req->ul_dev_name);
if (unlikely(id < 0)) {
MDDP_U_LOG(MDDP_LL_ERR,
"%s: Invalid dev_name, dev_name(%s)!\n",
__func__, in_req->ul_dev_name);
kfree(md_msg);
return -EINVAL;
}
memset(&limit, 0, sizeof(limit));
limit.cmd = MSG_ID_DPFM_SET_IQUOTA_REQ;
limit.trans_id = MDDP_U_GET_IQ_TRANS_ID();
limit.limit_buffer_size = in_req->limit_size;
limit.id = id;
MDDP_U_LOG(MDDP_LL_NOTICE,
"%s: Send cmd(%d)/id(%d)/name(%s) limit(%llx) to MD.\n",
__func__, limit.cmd, limit.id, in_req->ul_dev_name,
limit.limit_buffer_size);
md_msg->msg_id = IPC_MSG_ID_DPFM_DATA_USAGE_CMD;
md_msg->data_len = sizeof(limit);
memcpy(md_msg->data, &limit, sizeof(limit));
app = mddp_get_app_inst(MDDP_APP_TYPE_WH);
mddp_ipc_send_md(app, md_msg, MDFPM_USER_ID_DPFM);
return 0;
}
int32_t mddp_u_set_warning_and_data_limit(uint8_t *buf, uint32_t buf_len)
{
uint32_t md_status;
struct mddp_md_msg_t *md_msg;
struct mddp_dev_req_set_warning_and_data_limit_t *in_req;
struct mddp_u_warning_and_data_limit_t limit;
int8_t id;
struct mddp_app_t *app;
if (buf_len != sizeof(struct mddp_dev_req_set_warning_and_data_limit_t)) {
MDDP_U_LOG(MDDP_LL_ERR,
"%s: Invalid parameter, buf_len(%d)!\n",
__func__, buf_len);
return -EINVAL;
}
md_status = exec_ccci_kern_func_by_md_id(0, ID_GET_MD_STATE, NULL, 0);
if (md_status != MD_STATE_READY) {
MDDP_U_LOG(MDDP_LL_NOTICE,
"%s: Invalid state, md_status(%d)!\n",
__func__, md_status);
return -ENODEV;
}
md_msg = kzalloc(sizeof(struct mddp_md_msg_t) + sizeof(limit),
GFP_ATOMIC);
if (unlikely(!md_msg)) {
return -EAGAIN;
}
in_req = (struct mddp_dev_req_set_warning_and_data_limit_t *)buf;
id = mddp_f_data_usage_wan_dev_name_to_id(in_req->ul_dev_name);
if (unlikely(id < 0)) {
MDDP_U_LOG(MDDP_LL_ERR,
"%s: Invalid dev_name, dev_name(%s)!\n",
__func__, in_req->ul_dev_name);
kfree(md_msg);
return -EINVAL;
}
memset(&limit, 0, sizeof(limit));
limit.cmd = MSG_ID_DPFM_SET_IQUOTA_V2_REQ;
limit.trans_id = MDDP_U_GET_IQ_TRANS_ID();
limit.limit_buffer_size = in_req->limit_size;
limit.warning_buffer_size = in_req->warning_size;
limit.id = id;
MDDP_U_LOG(MDDP_LL_NOTICE,
"%s: Send cmd(%d)/id(%d)/name(%s) limit(%lld) warning(%lld) to MD.\n",
__func__, limit.cmd, limit.id, in_req->ul_dev_name,
limit.limit_buffer_size, limit.warning_buffer_size);
md_msg->msg_id = IPC_MSG_ID_DPFM_DATA_USAGE_CMD;
md_msg->data_len = sizeof(limit);
memcpy(md_msg->data, &limit, sizeof(limit));
app = mddp_get_app_inst(MDDP_APP_TYPE_WH);
mddp_ipc_send_md(app, md_msg, MDFPM_USER_ID_DPFM);
return 0;
}
int32_t mddp_u_msg_hdlr(uint32_t msg_id, void *buf, uint32_t buf_len)
{
int32_t ret = -EINVAL;
struct mddp_u_iquota_ind_t *ind;
if (msg_id == IPC_MSG_ID_DPFM_DATA_USAGE_CMD) {
ind = buf;
switch (ind->cmd) {
case MSG_ID_DPFM_ALERT_IQUOTA_IND:
mddp_dev_response(MDDP_APP_TYPE_ALL,
MDDP_CMCMD_LIMIT_IND, true, NULL, 0);
ret = 0;
break;
case MSG_ID_DPFM_ALERT_IQUOTA_WARNING_IND:
mddp_dev_response(MDDP_APP_TYPE_ALL,
MDDP_CMCMD_WARNING_IND, true, NULL, 0);
ret = 0;
break;
default:
break;
}
}
return ret;
}
void mddp_u_set_wan_iface(uint8_t *devname)
{
wan_id = mddp_f_data_usage_wan_dev_name_to_id(devname);
}