msm: ipa3: add support on socksv5 offload

Add the support to create an ipa-uc activation
table and pass the index to user-space module
to configure the v4nat/v6ct rules associated
with the uc-activation table index.

Change-Id: I14b4007dd80b64fb4a151b6b1413bea0c3a468f6
Signed-off-by: Skylar Chang <chiaweic@codeaurora.org>
Signed-off-by: Pooja Kumari <quic_kumarip@quicinc.com>
Signed-off-by: Muralidharan M <quic_murm@quicinc.com>
Dieser Commit ist enthalten in:
Muralidharan M
2020-02-04 17:09:16 -08:00
Ursprung b7482ec109
Commit b80d437e65
4 geänderte Dateien mit 339 neuen und 5 gelöschten Zeilen

Datei anzeigen

@@ -7277,6 +7277,8 @@ static inline void ipa3_register_to_fmwk(void)
ipa3_register_notifier;
data.ipa_unregister_notifier =
ipa3_unregister_notifier;
data.ipa_add_socksv5_conn = ipa3_add_socksv5_conn;
data.ipa_del_socksv5_conn = ipa3_del_socksv5_conn;
if (ipa_fmwk_register_ipa(&data)) {
IPAERR("couldn't register to IPA framework\n");
@@ -7702,6 +7704,10 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p,
IPADBG("register to fmwk\n");
ipa3_register_to_fmwk();
}
/* init uc-activation tbl*/
ipa3_setup_uc_act_tbl();
complete_all(&ipa3_ctx->init_completion_obj);
ipa_ut_module_init();
@@ -8637,6 +8643,9 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
ipa3_ctx->mpm_ring_size_dl = DEFAULT_MPM_RING_SIZE_DL;
ipa3_ctx->mpm_teth_aggr_size = DEFAULT_MPM_TETH_AGGR_SIZE;
ipa3_ctx->mpm_uc_thresh = DEFAULT_MPM_UC_THRESH_SIZE;
ipa3_ctx->uc_act_tbl_valid = false;
ipa3_ctx->uc_act_tbl_total = 0;
ipa3_ctx->uc_act_tbl_next_index = 0;
if (resource_p->gsi_fw_file_name) {
ipa3_ctx->gsi_fw_file_name =
@@ -8997,6 +9006,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
mutex_init(&ipa3_ctx->q6_proxy_clk_vote_mutex);
mutex_init(&ipa3_ctx->ipa_cne_evt_lock);
mutex_init(&ipa3_ctx->act_tbl_lock);
idr_init(&ipa3_ctx->ipa_idr);
spin_lock_init(&ipa3_ctx->idr_lock);

Datei anzeigen

@@ -344,6 +344,8 @@ enum {
#define IPA3_ACTIVE_CLIENTS_TABLE_BUF_SIZE 4096
#define IPA_UC_ACT_TBL_SIZE 1000
#define IPA3_ACTIVE_CLIENT_LOG_TYPE_EP 0
#define IPA3_ACTIVE_CLIENT_LOG_TYPE_SIMPLE 1
#define IPA3_ACTIVE_CLIENT_LOG_TYPE_RESOURCE 2
@@ -2386,6 +2388,11 @@ struct ipa3_context {
bool buff_below_thresh_for_def_pipe_notified;
bool buff_below_thresh_for_coal_pipe_notified;
u8 mhi_ctrl_state;
struct ipa_mem_buffer uc_act_tbl;
bool uc_act_tbl_valid;
struct mutex act_tbl_lock;
int uc_act_tbl_total;
int uc_act_tbl_next_index;
};
struct ipa3_plat_drv_res {
@@ -2796,6 +2803,12 @@ int ipa3_cfg_ep_ctrl(u32 clnt_hdl, const struct ipa_ep_cfg_ctrl *ep_ctrl);
int ipa3_cfg_ep_ulso(u32 clnt_hdl, const struct ipa_ep_cfg_ulso *ep_ulso);
int ipa3_setup_uc_act_tbl(void);
int ipa3_add_socksv5_conn(struct ipa_socksv5_info *info);
int ipa3_del_socksv5_conn(uint32_t handle);
/*
* Header removal / addition
*/

Datei anzeigen

@@ -12787,3 +12787,314 @@ void ipa3_update_mhi_ctrl_state(u8 state, bool set)
ipa_send_mhi_endp_ind_to_modem();
}
EXPORT_SYMBOL(ipa3_update_mhi_ctrl_state);
/**
* ipa3_setup_uc_act_tbl() - IPA setup uc_act_tbl
*
* Returns: 0 on success, negative on failure
*
* Note: Should not be called from atomic context
*/
int ipa3_setup_uc_act_tbl(void)
{
int res = 0;
struct ipa_mem_buffer *tbl;
struct ipahal_reg_nat_uc_external_cfg nat_ex_cfg;
struct ipahal_reg_nat_uc_shared_cfg nat_share_cfg;
struct ipahal_reg_conn_track_uc_external_cfg ct_ex_cfg;
struct ipahal_reg_conn_track_uc_shared_cfg ct_share_cfg;
/* IPA version check */
if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5) {
IPAERR("Not support!\n");
return -EPERM;
}
if (ipa3_ctx->uc_act_tbl_valid) {
IPAERR(" already allocate uC act tbl\n");
return -EEXIST;
}
tbl = &ipa3_ctx->uc_act_tbl;
/* Allocate uc act tbl */
tbl->size = sizeof(struct ipa_socksv5_uc_tmpl) * IPA_UC_ACT_TBL_SIZE;
tbl->base = dma_alloc_coherent(ipa3_ctx->pdev, tbl->size,
&tbl->phys_base, GFP_KERNEL);
if (tbl->base == NULL)
return -ENOMEM;
memset(tbl->base, 0, tbl->size);
ipa3_ctx->uc_act_tbl_valid = true;
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
/* LSB 32 bits*/
nat_ex_cfg.nat_uc_external_table_addr_lsb =
(u32) (tbl->phys_base & 0xFFFFFFFF);
ipahal_write_reg_fields(IPA_NAT_UC_EXTERNAL_CFG, &nat_ex_cfg);
/* MSB 16 bits */
nat_share_cfg.nat_uc_external_table_addr_msb =
(u16) (((tbl->phys_base & 0xFFFFFFFF00000000) >> 32) & 0xFFFF);
ipahal_write_reg_fields(IPA_NAT_UC_SHARED_CFG, &nat_share_cfg);
/* LSB 32 bits*/
ct_ex_cfg.conn_track_uc_external_table_addr_lsb =
(u32) (tbl->phys_base & 0xFFFFFFFF);
ipahal_write_reg_fields(IPA_CONN_TRACK_UC_EXTERNAL_CFG, &ct_ex_cfg);
/* MSB 16 bits */
ct_share_cfg.conn_track_uc_external_table_addr_msb =
(u16) (((tbl->phys_base & 0xFFFFFFFF00000000) >> 32) & 0xFFFF);
ipahal_write_reg_fields(IPA_CONN_TRACK_UC_SHARED_CFG, &ct_share_cfg);
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
return res;
}
static void ipa3_socksv5_msg_free_cb(void *buff, u32 len, u32 type)
{
if (!buff) {
IPAERR("Null buffer\n");
return;
}
if (type != IPA_SOCKV5_ADD &&
type != IPA_SOCKV5_DEL) {
IPAERR("Wrong type given. buff %pK type %d\n", buff, type);
kfree(buff);
return;
}
kfree(buff);
}
/**
* ipa3_add_socksv5_conn() - IPA add socksv5_conn
*
* Returns: 0 on success, negative on failure
*
* Note: Should not be called from atomic context
*/
int ipa3_add_socksv5_conn(struct ipa_socksv5_info *info)
{
int res = 0;
void *rp_va, *wp_va;
struct ipa_socksv5_msg *socksv5_msg;
struct ipa_msg_meta msg_meta;
/* IPA version check */
if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5) {
IPAERR("Not support !\n");
return -EPERM;
}
if (!ipa3_ctx->uc_act_tbl_valid) {
IPAERR("uC act tbl haven't allocated\n");
return -ENOENT;
}
if (!info) {
IPAERR("Null info\n");
return -EIO;
}
mutex_lock(&ipa3_ctx->act_tbl_lock);
/* check the left # of entries */
if (ipa3_ctx->uc_act_tbl_total
>= IPA_UC_ACT_TBL_SIZE) {
IPAERR("uc act tbl is full!\n");
res = -EFAULT;
goto error;
}
/* Copied the act-info to tbl */
wp_va = ipa3_ctx->uc_act_tbl.base +
ipa3_ctx->uc_act_tbl_next_index
* sizeof(struct ipa_socksv5_uc_tmpl);
/* check entry valid */
if ((info->ul_out.cmd_id != IPA_SOCKsv5_ADD_COM_ID)
|| (info->dl_out.cmd_id != IPA_SOCKsv5_ADD_COM_ID)) {
IPAERR("cmd_id not set UL%d DL%d!\n",
info->ul_out.cmd_id,
info->dl_out.cmd_id);
res = -EINVAL;
goto error;
}
if ((info->ul_out.cmd_param < IPA_SOCKsv5_ADD_V6_V4_COM_PM)
|| (info->ul_out.cmd_param > IPA_SOCKsv5_ADD_V6_V6_COM_PM)) {
IPAERR("ul cmd_param is not support%d!\n",
info->ul_out.cmd_param);
res = -EINVAL;
goto error;
}
if ((info->dl_out.cmd_param < IPA_SOCKsv5_ADD_V6_V4_COM_PM)
|| (info->dl_out.cmd_param > IPA_SOCKsv5_ADD_V6_V6_COM_PM)) {
IPAERR("dl cmd_param is not support%d!\n",
info->dl_out.cmd_param);
res = -EINVAL;
goto error;
}
/* indicate entry valid */
info->ul_out.ipa_sockv5_mask |= IPA_SOCKSv5_ENTRY_VALID;
info->dl_out.ipa_sockv5_mask |= IPA_SOCKSv5_ENTRY_VALID;
memcpy(wp_va, &(info->ul_out), sizeof(info->ul_out));
memcpy(wp_va + sizeof(struct ipa_socksv5_uc_tmpl),
&(info->dl_out), sizeof(info->dl_out));
/* set output handle */
info->handle = (uint16_t) ipa3_ctx->uc_act_tbl_next_index;
ipa3_ctx->uc_act_tbl_total += 2;
/* send msg to ipacm */
socksv5_msg = kzalloc(sizeof(*socksv5_msg), GFP_KERNEL);
if (!socksv5_msg) {
IPAERR("socksv5_msg memory allocation failed !\n");
res = -ENOMEM;
goto error;
}
memcpy(&(socksv5_msg->ul_in), &(info->ul_in), sizeof(info->ul_in));
memcpy(&(socksv5_msg->dl_in), &(info->dl_in), sizeof(info->dl_in));
socksv5_msg->handle = info->handle;
socksv5_msg->ul_in.index =
(uint16_t) ipa3_ctx->uc_act_tbl_next_index;
socksv5_msg->dl_in.index =
(uint16_t) ipa3_ctx->uc_act_tbl_next_index + 1;
memset(&msg_meta, 0, sizeof(struct ipa_msg_meta));
msg_meta.msg_type = IPA_SOCKV5_ADD;
msg_meta.msg_len = sizeof(struct ipa_socksv5_msg);
/* post event to ipacm*/
res = ipa3_send_msg(&msg_meta, socksv5_msg, ipa3_socksv5_msg_free_cb);
if (res) {
IPAERR_RL("ipa3_send_msg failed: %d\n", res);
kfree(socksv5_msg);
goto error;
}
if (ipa3_ctx->uc_act_tbl_total < IPA_UC_ACT_TBL_SIZE) {
/* find next free spot */
do {
ipa3_ctx->uc_act_tbl_next_index += 2;
ipa3_ctx->uc_act_tbl_next_index %=
IPA_UC_ACT_TBL_SIZE;
rp_va = ipa3_ctx->uc_act_tbl.base +
ipa3_ctx->uc_act_tbl_next_index
* sizeof(struct ipa_socksv5_uc_tmpl);
if (!((((struct ipa_socksv5_uc_tmpl *) rp_va)->
ipa_sockv5_mask) & IPA_SOCKSv5_ENTRY_VALID)) {
IPADBG("next available entry %d, total %d\n",
ipa3_ctx->uc_act_tbl_next_index,
ipa3_ctx->uc_act_tbl_total);
break;
}
} while (rp_va != wp_va);
if (rp_va == wp_va) {
/* set to max tbl size to debug */
IPAERR("can't find available spot!\n");
ipa3_ctx->uc_act_tbl_total = IPA_UC_ACT_TBL_SIZE;
res = -EFAULT;
}
}
error:
mutex_unlock(&ipa3_ctx->act_tbl_lock);
return res;
}
/**
* ipa3_del_socksv5_conn() - IPA add socksv5_conn
*
* Returns: 0 on success, negative on failure
*
* Note: Should not be called from atomic context
*/
int ipa3_del_socksv5_conn(uint32_t handle)
{
int res = 0;
void *rp_va;
uint32_t *socksv5_handle;
struct ipa_msg_meta msg_meta;
/* IPA version check */
if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5) {
IPAERR("Not support !\n");
return -EPERM;
}
if (!ipa3_ctx->uc_act_tbl_valid) {
IPAERR("uC act tbl haven't allocated\n");
return -ENOENT;
}
if (handle > IPA_UC_ACT_TBL_SIZE || handle < 0) {
IPAERR("invalid handle!\n");
return -EINVAL;
}
if ((handle % 2) != 0) {
IPAERR("invalid handle!\n");
return -EINVAL;
}
if (ipa3_ctx->uc_act_tbl_total < 2) {
IPAERR("invalid handle, all tbl is empty!\n");
return -EINVAL;
}
rp_va = ipa3_ctx->uc_act_tbl.base +
handle * sizeof(struct ipa_socksv5_uc_tmpl);
/* check entry is valid or not */
mutex_lock(&ipa3_ctx->act_tbl_lock);
if (!((((struct ipa_socksv5_uc_tmpl *) rp_va)->
ipa_sockv5_mask) & IPA_SOCKSv5_ENTRY_VALID)) {
IPADBG(" entry %d already free\n", handle);
}
if (!((((struct ipa_socksv5_uc_tmpl *) (rp_va +
sizeof(struct ipa_socksv5_uc_tmpl)))->
ipa_sockv5_mask) & IPA_SOCKSv5_ENTRY_VALID)) {
IPADBG(" entry %d already free\n", handle);
}
((struct ipa_socksv5_uc_tmpl *) rp_va)->ipa_sockv5_mask
&= ~IPA_SOCKSv5_ENTRY_VALID;
((struct ipa_socksv5_uc_tmpl *) (rp_va +
sizeof(struct ipa_socksv5_uc_tmpl)))->ipa_sockv5_mask
&= ~IPA_SOCKSv5_ENTRY_VALID;
ipa3_ctx->uc_act_tbl_total -= 2;
IPADBG("free entry %d and %d, left total %d\n",
handle,
handle + 1,
ipa3_ctx->uc_act_tbl_total);
/* send msg to ipacm */
socksv5_handle = kzalloc(sizeof(*socksv5_handle), GFP_KERNEL);
if (!socksv5_handle) {
IPAERR("socksv5_handle memory allocation failed!\n");
res = -ENOMEM;
goto error;
}
memcpy(socksv5_handle, &handle, sizeof(handle));
msg_meta.msg_type = IPA_SOCKV5_DEL;
msg_meta.msg_len = sizeof(uint32_t);
res = ipa3_send_msg(&msg_meta, socksv5_handle,
ipa3_socksv5_msg_free_cb);
if (res) {
IPAERR_RL("ipa3_send_msg failed: %d\n", res);
kfree(socksv5_handle);
}
error:
mutex_unlock(&ipa3_ctx->act_tbl_lock);
return res;
}

Datei anzeigen

@@ -242,16 +242,16 @@ static int ipa_nat_ipv6ct_stringify_entry_v_4_5(const void *entry,
char *buff, size_t buff_size)
{
int length;
const struct ipa_nat_hw_ipv4_entry *nat_entry =
(const struct ipa_nat_hw_ipv4_entry *)entry;
const struct ipa_nat_hw_ipv6ct_entry *ipv6ct_entry =
(const struct ipa_nat_hw_ipv6ct_entry *)entry;
length = ipa_nat_ipv6ct_stringify_entry_v_4_0(entry, buff, buff_size);
length += scnprintf(buff + length, buff_size - length,
"\t\tucp=%s address=%s uc_activation_index=%d\n",
(nat_entry->ucp) ? "Enabled" : "Disabled",
(nat_entry->s) ? "System" : "Local",
nat_entry->uc_activation_index);
(ipv6ct_entry->ucp) ? "Enabled" : "Disabled",
(ipv6ct_entry->s) ? "System" : "Local",
ipv6ct_entry->uc_activation_index);
return length;
}