msm: ipa: Dual NIC IPA offload support & ipa_eth client APIs refactor
Dual NIC IPA offload feature support including vlan. APIs refactor: 1. move the ipa_eth_conn/disconn_evt API inside ipa_eth_reg/unreg_intf. 2. deprecate the ipa_eth_conn/disconn_evt APIs. 3. add multiple eth vlan support Change-Id: Icb769df9a3f8a650bc47914e86150d75abfb479d Acked-by: Eliad Ben Yishay <ebenyish@qti.qualcomm.com> Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
Tento commit je obsažen v:

odevzdal
Gerrit - the friendly Code Review server

rodič
3b0bfb100b
revize
a06ad613b2
@@ -38,7 +38,7 @@
|
||||
OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
|
||||
} while (0)
|
||||
|
||||
#define IPA_ETH_PIPES_NO 6
|
||||
#define IPA_ETH_PIPES_NO 8
|
||||
|
||||
struct ipa_eth_ready_cb_wrapper {
|
||||
struct list_head link;
|
||||
@@ -108,6 +108,12 @@ static u8 client_to_pipe_index(enum ipa_client_type client_type)
|
||||
case IPA_CLIENT_AQC_ETHERNET_PROD:
|
||||
return 5;
|
||||
break;
|
||||
case IPA_CLIENT_ETHERNET2_CONS:
|
||||
return 6;
|
||||
break;
|
||||
case IPA_CLIENT_ETHERNET2_PROD:
|
||||
return 7;
|
||||
break;
|
||||
default:
|
||||
IPAERR("invalid eth client_type\n");
|
||||
ipa_assert();
|
||||
@@ -397,6 +403,25 @@ static enum ipa_client_type
|
||||
}
|
||||
}
|
||||
break;
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
case IPA_ETH_CLIENT_NTN3:
|
||||
if (client->traffic_type == IPA_ETH_PIPE_BEST_EFFORT) {
|
||||
if (client->inst_id == 0) {
|
||||
if (pipe->dir == IPA_ETH_PIPE_DIR_TX) {
|
||||
ipa_client_type = IPA_CLIENT_ETHERNET_CONS;
|
||||
} else {
|
||||
ipa_client_type = IPA_CLIENT_ETHERNET_PROD;
|
||||
}
|
||||
} else if (client->inst_id == 1) {
|
||||
if (pipe->dir == IPA_ETH_PIPE_DIR_TX) {
|
||||
ipa_client_type = IPA_CLIENT_ETHERNET2_CONS;
|
||||
} else {
|
||||
ipa_client_type = IPA_CLIENT_ETHERNET2_PROD;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
IPA_ETH_ERR("invalid client type%d\n",
|
||||
client->client_type);
|
||||
@@ -714,7 +739,8 @@ static int ipa_eth_client_disconn_pipes_internal(struct ipa_eth_client *client)
|
||||
pipe->dir);
|
||||
holb.en = 1;
|
||||
holb.tmr_val = 0;
|
||||
ipa3_cfg_ep_holb(ipa_get_ep_mapping(ipa_eth_get_ipa_client_type_from_pipe(pipe)), &holb);
|
||||
ipa3_cfg_ep_holb(ipa_get_ep_mapping(
|
||||
ipa_eth_get_ipa_client_type_from_pipe(pipe)), &holb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -735,6 +761,59 @@ static int ipa_eth_client_disconn_pipes_internal(struct ipa_eth_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ipa_eth_msg_free_cb(void *buff, u32 len, u32 type)
|
||||
{
|
||||
kfree(buff);
|
||||
}
|
||||
|
||||
static int ipa_eth_client_conn_evt_internal(struct ipa_ecm_msg *msg)
|
||||
{
|
||||
struct ipa_msg_meta msg_meta;
|
||||
struct ipa_ecm_msg *eth_msg;
|
||||
int ret;
|
||||
|
||||
IPA_ETH_DBG("enter\n");
|
||||
|
||||
eth_msg = kzalloc(sizeof(*eth_msg), GFP_KERNEL);
|
||||
if (eth_msg == NULL)
|
||||
return -ENOMEM;
|
||||
memcpy(eth_msg, msg, sizeof(struct ipa_ecm_msg));
|
||||
memset(&msg_meta, 0, sizeof(struct ipa_msg_meta));
|
||||
msg_meta.msg_len = sizeof(struct ipa_ecm_msg);
|
||||
msg_meta.msg_type = IPA_PERIPHERAL_CONNECT;
|
||||
|
||||
IPA_ETH_DBG("send IPA_PERIPHERAL_CONNECT, len:%d, buff %pK", msg_meta.msg_len, eth_msg);
|
||||
ret = ipa_send_msg(&msg_meta, eth_msg, ipa_eth_msg_free_cb);
|
||||
|
||||
IPA_ETH_DBG("exit\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ipa_eth_client_disconn_evt_internal(struct ipa_ecm_msg *msg)
|
||||
{
|
||||
struct ipa_msg_meta msg_meta;
|
||||
struct ipa_ecm_msg *eth_msg;
|
||||
int ret;
|
||||
|
||||
IPA_ETH_DBG("enter\n");
|
||||
|
||||
eth_msg = kzalloc(sizeof(*eth_msg), GFP_KERNEL);
|
||||
if (eth_msg == NULL)
|
||||
return -ENOMEM;
|
||||
memcpy(eth_msg, msg, sizeof(struct ipa_ecm_msg));
|
||||
memset(&msg_meta, 0, sizeof(struct ipa_msg_meta));
|
||||
msg_meta.msg_len = sizeof(struct ipa_ecm_msg);
|
||||
msg_meta.msg_type = IPA_PERIPHERAL_DISCONNECT;
|
||||
|
||||
IPA_ETH_DBG("send PERIPHERAL_DISCONNECT, len:%d, buff %pK", msg_meta.msg_len, eth_msg);
|
||||
ret = ipa_send_msg(&msg_meta, eth_msg, ipa_eth_msg_free_cb);
|
||||
|
||||
IPA_ETH_DBG("exit\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ipa_eth_client_reg_intf_internal(struct ipa_eth_intf_info *intf)
|
||||
{
|
||||
struct ipa_eth_intf *new_intf;
|
||||
@@ -749,6 +828,13 @@ static int ipa_eth_client_reg_intf_internal(struct ipa_eth_intf_info *intf)
|
||||
struct ipa_eth_client_pipe_info *pipe;
|
||||
u32 len;
|
||||
int ret = 0, i;
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
struct ipa_ecm_msg msg;
|
||||
bool vlan_mode = false;
|
||||
struct ipa_eth_hdr_info intf_hdr[IPA_IP_MAX];
|
||||
struct ethhdr l_ethhdr[IPA_IP_MAX] = { 0 };
|
||||
struct vlan_ethhdr l_vlan_ethhdr[IPA_IP_MAX] = { 0 };
|
||||
#endif
|
||||
|
||||
if (intf == NULL) {
|
||||
IPA_ETH_ERR("invalid params intf=%pK\n", intf);
|
||||
@@ -758,15 +844,92 @@ static int ipa_eth_client_reg_intf_internal(struct ipa_eth_intf_info *intf)
|
||||
IPA_ETH_ERR("disconn called before register readiness\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
if (!intf->client) {
|
||||
IPA_ETH_ERR("invalid intf->client\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (!intf->client->net_dev) {
|
||||
IPA_ETH_ERR("invalid netdev\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (!intf->net_dev)
|
||||
intf->net_dev = intf->client->net_dev;
|
||||
|
||||
IPA_ETH_DBG("register interface for netdev %s\n", intf->net_dev->name);
|
||||
/* multiple attach support */
|
||||
if (strnstr(intf->net_dev->name, "eth0", strlen(intf->net_dev->name))) {
|
||||
ret = ipa3_is_vlan_mode(IPA_VLAN_IF_ETH0, &vlan_mode);
|
||||
if (ret) {
|
||||
IPA_ETH_ERR("Could not determine IPA VLAN mode\n");
|
||||
return ret;
|
||||
}
|
||||
} else if (strnstr(intf->net_dev->name, "eth1", strlen(intf->net_dev->name))) {
|
||||
ret = ipa3_is_vlan_mode(IPA_VLAN_IF_ETH1, &vlan_mode);
|
||||
if (ret) {
|
||||
IPA_ETH_ERR("Could not determine IPA VLAN mode\n");
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
ret = ipa3_is_vlan_mode(IPA_VLAN_IF_ETH, &vlan_mode);
|
||||
if (ret) {
|
||||
IPA_ETH_ERR("Could not determine IPA VLAN mode\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#else
|
||||
IPA_ETH_DBG("register interface for netdev %s\n",
|
||||
intf->netdev_name);
|
||||
#endif
|
||||
mutex_lock(&ipa_eth_ctx->lock);
|
||||
list_for_each_entry(entry, &ipa_eth_ctx->head_intf_list, link)
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
if (strcmp(entry->netdev_name, intf->net_dev->name) == 0) {
|
||||
#else
|
||||
if (strcmp(entry->netdev_name, intf->netdev_name) == 0) {
|
||||
#endif
|
||||
IPA_ETH_DBG("intf was added before.\n");
|
||||
mutex_unlock(&ipa_eth_ctx->lock);
|
||||
return 0;
|
||||
}
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
memset(intf_hdr, 0, sizeof(intf_hdr));
|
||||
if (!vlan_mode) {
|
||||
struct ethhdr *eth_h;
|
||||
|
||||
intf_hdr[0].hdr = (u8 *)&l_ethhdr[0];
|
||||
eth_h = (struct ethhdr *) intf_hdr[0].hdr;
|
||||
memcpy(ð_h->h_source, intf->net_dev->dev_addr, ETH_ALEN);
|
||||
eth_h->h_proto = htons(ETH_P_IP);
|
||||
intf_hdr[0].hdr_len = ETH_HLEN;
|
||||
intf_hdr[0].hdr_type = IPA_HDR_L2_ETHERNET_II;
|
||||
|
||||
intf_hdr[1].hdr = (u8 *)&l_ethhdr[1];
|
||||
eth_h = (struct ethhdr *) intf_hdr[1].hdr;
|
||||
memcpy(ð_h->h_source, intf->net_dev->dev_addr, ETH_ALEN);
|
||||
eth_h->h_proto = htons(ETH_P_IPV6);
|
||||
intf_hdr[1].hdr_len = ETH_HLEN;
|
||||
intf_hdr[1].hdr_type = IPA_HDR_L2_ETHERNET_II;
|
||||
} else {
|
||||
struct vlan_ethhdr *vlan_eth_h;
|
||||
|
||||
intf_hdr[0].hdr = (u8 *)&l_vlan_ethhdr[0];
|
||||
vlan_eth_h = (struct vlan_ethhdr *) intf_hdr[0].hdr;
|
||||
memcpy(&vlan_eth_h->h_source, intf->net_dev->dev_addr, ETH_ALEN);
|
||||
vlan_eth_h->h_vlan_proto = htons(ETH_P_8021Q);
|
||||
vlan_eth_h->h_vlan_encapsulated_proto = htons(ETH_P_IP);
|
||||
intf_hdr[0].hdr_len = VLAN_ETH_HLEN;
|
||||
intf_hdr[0].hdr_type = IPA_HDR_L2_802_1Q;
|
||||
|
||||
intf_hdr[1].hdr = (u8 *)&l_vlan_ethhdr[1];
|
||||
vlan_eth_h = (struct vlan_ethhdr *) intf_hdr[1].hdr;
|
||||
memcpy(&vlan_eth_h->h_source, intf->net_dev->dev_addr, ETH_ALEN);
|
||||
vlan_eth_h->h_vlan_proto = htons(ETH_P_8021Q);
|
||||
vlan_eth_h->h_vlan_encapsulated_proto = htons(ETH_P_IPV6);
|
||||
intf_hdr[1].hdr_len = VLAN_ETH_HLEN;
|
||||
intf_hdr[1].hdr_type = IPA_HDR_L2_802_1Q;;
|
||||
}
|
||||
#endif
|
||||
new_intf = kzalloc(sizeof(*new_intf), GFP_KERNEL);
|
||||
if (new_intf == NULL) {
|
||||
IPA_ETH_ERR("fail to alloc new intf\n");
|
||||
@@ -774,9 +937,14 @@ static int ipa_eth_client_reg_intf_internal(struct ipa_eth_intf_info *intf)
|
||||
return -ENOMEM;
|
||||
}
|
||||
INIT_LIST_HEAD(&new_intf->link);
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
strlcpy(new_intf->netdev_name, intf->net_dev->name, sizeof(new_intf->netdev_name));
|
||||
new_intf->hdr_len = intf_hdr[0].hdr_len;
|
||||
#else
|
||||
strlcpy(new_intf->netdev_name, intf->netdev_name,
|
||||
sizeof(new_intf->netdev_name));
|
||||
new_intf->hdr_len = intf->hdr[0].hdr_len;
|
||||
#endif
|
||||
/* add partial header */
|
||||
len = sizeof(struct ipa_ioc_add_hdr) + 2 * sizeof(struct ipa_hdr_add);
|
||||
hdr = kzalloc(len, GFP_KERNEL);
|
||||
@@ -785,9 +953,12 @@ static int ipa_eth_client_reg_intf_internal(struct ipa_eth_intf_info *intf)
|
||||
ret = -EFAULT;
|
||||
goto fail_alloc_hdr;
|
||||
}
|
||||
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
if (ipa_eth_commit_partial_hdr(hdr, intf->net_dev->name, (struct ipa_eth_hdr_info *)intf_hdr)) {
|
||||
#else
|
||||
if (ipa_eth_commit_partial_hdr(hdr,
|
||||
intf->netdev_name, intf->hdr)) {
|
||||
#endif
|
||||
IPA_ETH_ERR("fail to commit partial headers\n");
|
||||
ret = -EFAULT;
|
||||
goto fail_commit_hdr;
|
||||
@@ -800,8 +971,12 @@ static int ipa_eth_client_reg_intf_internal(struct ipa_eth_intf_info *intf)
|
||||
|
||||
memset(&tx, 0, sizeof(struct ipa_tx_intf));
|
||||
memset(&rx, 0, sizeof(struct ipa_rx_intf));
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
list_for_each_entry(pipe, &intf->client->pipe_list, link) {
|
||||
#else
|
||||
for (i = 0; i < intf->pipe_hdl_list_size; i++) {
|
||||
pipe = ipa_eth_get_pipe_from_hdl(intf->pipe_hdl_list[i]);
|
||||
#endif
|
||||
if (pipe->dir == IPA_ETH_PIPE_DIR_TX) {
|
||||
tx_client[tx.num_props] =
|
||||
ipa_eth_get_ipa_client_type_from_pipe(pipe);
|
||||
@@ -828,13 +1003,21 @@ static int ipa_eth_client_reg_intf_internal(struct ipa_eth_intf_info *intf)
|
||||
for (i = 0; i < tx.num_props; i++) {
|
||||
tx_prop[i].ip = IPA_IP_v4;
|
||||
tx_prop[i].dst_pipe = tx_client[i];
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
tx_prop[i].hdr_l2_type = intf_hdr[0].hdr_type;
|
||||
#else
|
||||
tx_prop[i].hdr_l2_type = intf->hdr[0].hdr_type;
|
||||
#endif
|
||||
strlcpy(tx_prop[i].hdr_name, hdr->hdr[IPA_IP_v4].name,
|
||||
sizeof(tx_prop[i].hdr_name));
|
||||
|
||||
tx_prop[i+1].ip = IPA_IP_v6;
|
||||
tx_prop[i+1].dst_pipe = tx_client[i];
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
tx_prop[i+1].hdr_l2_type = intf_hdr[1].hdr_type;
|
||||
#else
|
||||
tx_prop[i+1].hdr_l2_type = intf->hdr[1].hdr_type;
|
||||
#endif
|
||||
strlcpy(tx_prop[i+1].hdr_name, hdr->hdr[IPA_IP_v6].name,
|
||||
sizeof(tx_prop[i+1].hdr_name));
|
||||
}
|
||||
@@ -855,16 +1038,27 @@ static int ipa_eth_client_reg_intf_internal(struct ipa_eth_intf_info *intf)
|
||||
for (i = 0; i < rx.num_props; i++) {
|
||||
rx_prop[i].ip = IPA_IP_v4;
|
||||
rx_prop[i].src_pipe = rx_client[i];
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
rx_prop[i].hdr_l2_type = intf_hdr[0].hdr_type;
|
||||
#else
|
||||
rx_prop[i].hdr_l2_type = intf->hdr[0].hdr_type;
|
||||
|
||||
#endif
|
||||
rx_prop[i+1].ip = IPA_IP_v6;
|
||||
rx_prop[i+1].src_pipe = rx_client[i];
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
rx_prop[i+1].hdr_l2_type = intf_hdr[1].hdr_type;
|
||||
#else
|
||||
rx_prop[i+1].hdr_l2_type = intf->hdr[1].hdr_type;
|
||||
#endif
|
||||
}
|
||||
tx.num_props *= IPA_IP_MAX;
|
||||
rx.num_props *= IPA_IP_MAX;
|
||||
}
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
if (ipa_register_intf(intf->net_dev->name, &tx, &rx)) {
|
||||
#else
|
||||
if (ipa_register_intf(intf->netdev_name, &tx, &rx)) {
|
||||
#endif
|
||||
IPA_ETH_ERR("fail to add interface prop\n");
|
||||
ret = -EFAULT;
|
||||
goto fail_commit_hdr;
|
||||
@@ -876,6 +1070,14 @@ static int ipa_eth_client_reg_intf_internal(struct ipa_eth_intf_info *intf)
|
||||
kfree(tx_prop);
|
||||
kfree(rx_prop);
|
||||
mutex_unlock(&ipa_eth_ctx->lock);
|
||||
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
if (intf->is_conn_evt) {
|
||||
strlcpy(msg.name, intf->net_dev->name, sizeof(msg.name));
|
||||
msg.ifindex = intf->net_dev->ifindex;
|
||||
ipa_eth_client_conn_evt_internal(&msg);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
fail_commit_hdr:
|
||||
kfree(hdr);
|
||||
@@ -893,6 +1095,9 @@ static int ipa_eth_client_unreg_intf_internal(struct ipa_eth_intf_info *intf)
|
||||
struct ipa_ioc_del_hdr *hdr = NULL;
|
||||
struct ipa_eth_intf *entry;
|
||||
struct ipa_eth_intf *next;
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
struct ipa_ecm_msg msg;
|
||||
#endif
|
||||
|
||||
if (intf == NULL) {
|
||||
IPA_ETH_ERR("invalid params intf=%pK\n", intf);
|
||||
@@ -902,12 +1107,24 @@ static int ipa_eth_client_unreg_intf_internal(struct ipa_eth_intf_info *intf)
|
||||
IPA_ETH_ERR("disconn called before register readiness\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
if (!intf->net_dev) {
|
||||
IPA_ETH_ERR("invalid netdev\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
IPA_ETH_DBG("unregister interface for netdev %s\n", intf->net_dev->name);
|
||||
#else
|
||||
IPA_ETH_DBG("unregister interface for netdev %s\n",
|
||||
intf->netdev_name);
|
||||
#endif
|
||||
mutex_lock(&ipa_eth_ctx->lock);
|
||||
list_for_each_entry_safe(entry, next, &ipa_eth_ctx->head_intf_list,
|
||||
link)
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
if (strcmp(entry->netdev_name, intf->net_dev->name) == 0) {
|
||||
#else
|
||||
if (strcmp(entry->netdev_name, intf->netdev_name) == 0) {
|
||||
#endif
|
||||
len = sizeof(struct ipa_ioc_del_hdr) +
|
||||
IPA_IP_MAX * sizeof(struct ipa_hdr_del);
|
||||
hdr = kzalloc(len, GFP_KERNEL);
|
||||
@@ -944,6 +1161,13 @@ static int ipa_eth_client_unreg_intf_internal(struct ipa_eth_intf_info *intf)
|
||||
fail:
|
||||
kfree(hdr);
|
||||
mutex_unlock(&ipa_eth_ctx->lock);
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
if (intf->is_conn_evt) {
|
||||
strlcpy(msg.name, intf->net_dev->name, sizeof(msg.name));
|
||||
msg.ifindex = intf->net_dev->ifindex;
|
||||
ipa_eth_client_disconn_evt_internal(&msg);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
|
||||
}
|
||||
@@ -971,61 +1195,6 @@ static int ipa_eth_client_set_perf_profile_internal(struct ipa_eth_client *clien
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ipa_eth_msg_free_cb(void *buff, u32 len, u32 type)
|
||||
{
|
||||
kfree(buff);
|
||||
}
|
||||
|
||||
static int ipa_eth_client_conn_evt_internal(struct ipa_ecm_msg *msg)
|
||||
{
|
||||
struct ipa_msg_meta msg_meta;
|
||||
struct ipa_ecm_msg *eth_msg;
|
||||
int ret;
|
||||
|
||||
IPADBG("enter\n");
|
||||
|
||||
eth_msg = kzalloc(sizeof(*eth_msg), GFP_KERNEL);
|
||||
if (eth_msg == NULL)
|
||||
return -ENOMEM;
|
||||
memcpy(eth_msg, msg, sizeof(struct ipa_ecm_msg));
|
||||
memset(&msg_meta, 0, sizeof(struct ipa_msg_meta));
|
||||
msg_meta.msg_len = sizeof(struct ipa_ecm_msg);
|
||||
msg_meta.msg_type = IPA_PERIPHERAL_CONNECT;
|
||||
|
||||
IPADBG("send IPA_PERIPHERAL_CONNECT, len:%d, buff %pK",
|
||||
msg_meta.msg_len, eth_msg);
|
||||
ret = ipa_send_msg(&msg_meta, eth_msg, ipa_eth_msg_free_cb);
|
||||
|
||||
IPADBG("exit\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ipa_eth_client_disconn_evt_internal(struct ipa_ecm_msg *msg)
|
||||
{
|
||||
struct ipa_msg_meta msg_meta;
|
||||
struct ipa_ecm_msg *eth_msg;
|
||||
int ret;
|
||||
|
||||
IPADBG("enter\n");
|
||||
|
||||
eth_msg = kzalloc(sizeof(*eth_msg), GFP_KERNEL);
|
||||
if (eth_msg == NULL)
|
||||
return -ENOMEM;
|
||||
memcpy(eth_msg, msg, sizeof(struct ipa_ecm_msg));
|
||||
memset(&msg_meta, 0, sizeof(struct ipa_msg_meta));
|
||||
msg_meta.msg_len = sizeof(struct ipa_ecm_msg);
|
||||
msg_meta.msg_type = IPA_PERIPHERAL_DISCONNECT;
|
||||
|
||||
IPADBG("send PERIPHERAL_DISCONNECT, len:%d, buff %pK",
|
||||
msg_meta.msg_len, eth_msg);
|
||||
ret = ipa_send_msg(&msg_meta, eth_msg, ipa_eth_msg_free_cb);
|
||||
|
||||
IPADBG("exit\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum ipa_client_type ipa_eth_get_ipa_client_type_from_eth_type_internal(
|
||||
enum ipa_eth_client_type eth_client_type, enum ipa_eth_pipe_direction dir)
|
||||
{
|
||||
@@ -1090,8 +1259,10 @@ void ipa_eth_register(void)
|
||||
funcs.ipa_eth_client_unreg_intf = ipa_eth_client_unreg_intf_internal;
|
||||
funcs.ipa_eth_client_set_perf_profile =
|
||||
ipa_eth_client_set_perf_profile_internal;
|
||||
#if IPA_ETH_API_VER < 2
|
||||
funcs.ipa_eth_client_conn_evt = ipa_eth_client_conn_evt_internal;
|
||||
funcs.ipa_eth_client_disconn_evt = ipa_eth_client_disconn_evt_internal;
|
||||
#endif
|
||||
funcs.ipa_eth_get_ipa_client_type_from_eth_type =
|
||||
ipa_eth_get_ipa_client_type_from_eth_type_internal;
|
||||
funcs.ipa_eth_client_exist = ipa_eth_client_exist_internal;
|
||||
|
@@ -19,6 +19,10 @@
|
||||
#include "ipa_stats.h"
|
||||
#include "gsi.h"
|
||||
|
||||
#ifndef IPA_ETH_API_VER
|
||||
#define IPA_ETH_API_VER 1
|
||||
#endif
|
||||
|
||||
#define WARNON_RATELIMIT_BURST 1
|
||||
#define IPA_RATELIMIT_BURST 1
|
||||
#define IPA_EP_ARR_SIZE 2
|
||||
@@ -882,10 +886,13 @@ int ipa_eth_emac_disconnect(
|
||||
struct ipa_eth_client_pipe_info *pipe,
|
||||
enum ipa_client_type client_type);
|
||||
|
||||
#if IPA_ETH_API_VER < 2
|
||||
int ipa_eth_client_conn_evt(struct ipa_ecm_msg *msg);
|
||||
|
||||
int ipa_eth_client_disconn_evt(struct ipa_ecm_msg *msg);
|
||||
|
||||
#endif
|
||||
|
||||
/* ULSO mode Query */
|
||||
bool ipa3_is_ulso_supported(void);
|
||||
|
||||
|
@@ -8017,6 +8017,18 @@ static ssize_t ipa3_write(struct file *file, const char __user *buf,
|
||||
if (strnstr(dbg_buff, "eth", strlen(dbg_buff)))
|
||||
ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_EMAC] =
|
||||
true;
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
/* In Dual NIC mode we get "vlan: eth [eth0|eth1] [eth0|eth1]?" while device name is
|
||||
"eth0" in legacy so, we set it to false to diffrentiate Dual NIC from legacy */
|
||||
if (strnstr(dbg_buff, "eth0", strlen(dbg_buff))) {
|
||||
ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_ETH0] = true;
|
||||
ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_EMAC] = false;
|
||||
}
|
||||
if (strnstr(dbg_buff, "eth1", strlen(dbg_buff))){
|
||||
ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_ETH1] = true;
|
||||
ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_EMAC] = false;
|
||||
}
|
||||
#endif
|
||||
if (strnstr(dbg_buff, "rndis", strlen(dbg_buff)))
|
||||
ipa3_ctx->vlan_mode_iface[IPA_VLAN_IF_RNDIS] =
|
||||
true;
|
||||
|
@@ -880,6 +880,9 @@ static int ipa3_eth_get_prot(struct ipa_eth_client_pipe_info *pipe,
|
||||
*prot = IPA_HW_PROTOCOL_RTK;
|
||||
break;
|
||||
case IPA_ETH_CLIENT_NTN:
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
case IPA_ETH_CLIENT_NTN3:
|
||||
#endif
|
||||
*prot = IPA_HW_PROTOCOL_NTN3;
|
||||
break;
|
||||
case IPA_ETH_CLIENT_EMAC:
|
||||
@@ -910,6 +913,9 @@ int ipa3_eth_connect(
|
||||
int ch;
|
||||
u64 bar_addr;
|
||||
enum ipa4_hw_protocol prot;
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
struct net_device *net_dev;
|
||||
#endif
|
||||
|
||||
ep_idx = ipa_get_ep_mapping(client_type);
|
||||
if (ep_idx == -1 || ep_idx >= IPA3_MAX_NUM_PIPES) {
|
||||
@@ -931,12 +937,36 @@ int ipa3_eth_connect(
|
||||
}
|
||||
}
|
||||
|
||||
/* need enhancement for vlan support on multiple attach */
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
net_dev = pipe->client_info->net_dev;
|
||||
|
||||
/* multiple attach support */
|
||||
if (strnstr(net_dev->name, "eth0", strlen(net_dev->name))) {
|
||||
result = ipa3_is_vlan_mode(IPA_VLAN_IF_ETH0, &vlan_mode);
|
||||
if (result) {
|
||||
IPAERR("Could not determine IPA VLAN mode\n");
|
||||
return result;
|
||||
}
|
||||
} else if (strnstr(net_dev->name, "eth1", strlen(net_dev->name))) {
|
||||
result = ipa3_is_vlan_mode(IPA_VLAN_IF_ETH1, &vlan_mode);
|
||||
if (result) {
|
||||
IPAERR("Could not determine IPA VLAN mode\n");
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
result = ipa3_is_vlan_mode(IPA_VLAN_IF_ETH, &vlan_mode);
|
||||
if (result) {
|
||||
IPAERR("Could not determine IPA VLAN mode\n");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#else
|
||||
result = ipa3_is_vlan_mode(IPA_VLAN_IF_ETH, &vlan_mode);
|
||||
if (result) {
|
||||
IPAERR("Could not determine IPA VLAN mode\n");
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
result = ipa3_eth_get_prot(pipe, &prot);
|
||||
if (result) {
|
||||
|
@@ -3438,8 +3438,10 @@ int ipa3_eth_connect(
|
||||
int ipa3_eth_disconnect(
|
||||
struct ipa_eth_client_pipe_info *pipe,
|
||||
enum ipa_client_type client_type);
|
||||
#if IPA_ETH_API_VER < 2
|
||||
int ipa3_eth_client_conn_evt(struct ipa_ecm_msg *msg);
|
||||
int ipa3_eth_client_disconn_evt(struct ipa_ecm_msg *msg);
|
||||
#endif
|
||||
void ipa3_eth_get_status(u32 client, int scratch_id,
|
||||
struct ipa3_eth_error_stats *stats);
|
||||
int ipa3_get_gsi_chan_info(struct gsi_chan_info *gsi_chan_info,
|
||||
|
@@ -4092,7 +4092,7 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
|
||||
true,
|
||||
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
|
||||
QMB_MASTER_SELECT_DDR,
|
||||
{ 3 , 15, 8 , 16, IPA_EE_AP, GSI_SMART_PRE_FETCH, 3},
|
||||
{ 3 , 7, 8 , 16, IPA_EE_AP, GSI_SMART_PRE_FETCH, 3},
|
||||
IPA_TX_INSTANCE_NA },
|
||||
[IPA_5_0][IPA_CLIENT_APPS_LAN_PROD] = {
|
||||
true, IPA_v5_0_GROUP_DL,
|
||||
|
@@ -47,6 +47,9 @@ struct ipa_test_ntn_context {
|
||||
int tx_db_local;
|
||||
int rx_idx;
|
||||
int tx_idx;
|
||||
enum ipa_client_type cons_client_type;
|
||||
enum ipa_client_type prod_client_type;
|
||||
int eth_client_inst_id;
|
||||
};
|
||||
|
||||
static struct ipa_test_ntn_context *test_ntn_ctx;
|
||||
@@ -101,6 +104,14 @@ struct rx_event_ring_ele
|
||||
uint32_t own : 1;
|
||||
}__packed;
|
||||
|
||||
static inline void ipa_test_ntn_set_client_params(enum ipa_client_type cons_type,
|
||||
enum ipa_client_type prod_type, int inst_id)
|
||||
{
|
||||
test_ntn_ctx->cons_client_type = cons_type;
|
||||
test_ntn_ctx->prod_client_type = prod_type;
|
||||
test_ntn_ctx->eth_client_inst_id = inst_id;
|
||||
}
|
||||
|
||||
static void ipa_test_ntn_free_dma_buff(struct ipa_mem_buffer *mem)
|
||||
{
|
||||
struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN);
|
||||
@@ -397,6 +408,8 @@ static int ipa_test_ntn_suite_setup(void **priv)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ipa_test_ntn_set_client_params(IPA_CLIENT_ETHERNET_CONS, IPA_CLIENT_ETHERNET_PROD, 0);
|
||||
|
||||
init_completion(&test_ntn_ctx->init_completion_obj);
|
||||
|
||||
/*
|
||||
@@ -468,8 +481,8 @@ static void ipa_ntn_test_print_stats()
|
||||
stats.u.ring[0].RingUtilCount);
|
||||
|
||||
/* now get gsi stats */
|
||||
tx_ep = IPA_CLIENT_ETHERNET_CONS;
|
||||
rx_ep = IPA_CLIENT_ETHERNET_PROD;
|
||||
tx_ep = test_ntn_ctx->cons_client_type;
|
||||
rx_ep = test_ntn_ctx->prod_client_type;
|
||||
ipa3_eth_get_status(tx_ep, 6, &tx_stats);
|
||||
ipa3_eth_get_status(rx_ep, 6, &rx_stats);
|
||||
|
||||
@@ -532,10 +545,23 @@ static int ipa_ntn_test_setup_pipes(void)
|
||||
{
|
||||
struct ipa_eth_client *client;
|
||||
int ret, i;
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
struct net_device dummy_net_dev;
|
||||
unsigned char dummy_dev_addr = 1;
|
||||
|
||||
memset(dummy_net_dev.name, 0, sizeof(dummy_net_dev.name));
|
||||
dummy_net_dev.dev_addr = &dummy_dev_addr;
|
||||
|
||||
test_ntn_ctx->client.client_type = IPA_ETH_CLIENT_NTN3;
|
||||
test_ntn_ctx->client.inst_id = test_ntn_ctx->eth_client_inst_id;
|
||||
#else
|
||||
test_ntn_ctx->client.client_type = IPA_ETH_CLIENT_NTN;
|
||||
test_ntn_ctx->client.inst_id = 0;
|
||||
#endif
|
||||
test_ntn_ctx->client.traffic_type = IPA_ETH_PIPE_BEST_EFFORT;
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
test_ntn_ctx->client.net_dev = &dummy_net_dev;
|
||||
#endif
|
||||
|
||||
/* RX pipe */
|
||||
/* ring */
|
||||
@@ -675,11 +701,26 @@ conn_failed:
|
||||
static int ipa_ntn_test_reg_intf(void)
|
||||
{
|
||||
struct ipa_eth_intf_info intf;
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
struct net_device dummy_net_dev;
|
||||
unsigned char dummy_dev_addr[ETH_ALEN] = { 0 };
|
||||
#else
|
||||
char netdev_name[IPA_RESOURCE_NAME_MAX] = { 0 };
|
||||
int ret = 0;
|
||||
u8 hdr_content = 1;
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
memset(&intf, 0, sizeof(intf));
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
memset(dummy_net_dev.name, 0, sizeof(dummy_net_dev.name));
|
||||
|
||||
intf.net_dev = &dummy_net_dev;
|
||||
intf.net_dev->dev_addr = (unsigned char *)dummy_dev_addr;
|
||||
intf.is_conn_evt = true;
|
||||
|
||||
snprintf(intf.net_dev->name, sizeof(intf.net_dev->name), "ntn_test");
|
||||
IPA_UT_INFO("netdev name: %s strlen: %lu\n", intf.net_dev->name, strlen(intf.net_dev->name));
|
||||
#else
|
||||
snprintf(netdev_name, sizeof(netdev_name), "ntn_test");
|
||||
intf.netdev_name = netdev_name;
|
||||
IPA_UT_INFO("netdev name: %s strlen: %lu\n", intf.netdev_name,
|
||||
@@ -707,13 +748,17 @@ static int ipa_ntn_test_reg_intf(void)
|
||||
intf.pipe_hdl_list[0] = test_ntn_ctx->rx_pipe_info.pipe_hdl;
|
||||
intf.pipe_hdl_list[1] = test_ntn_ctx->tx_pipe_info.pipe_hdl;
|
||||
intf.pipe_hdl_list_size = IPA_TEST_NTN_NUM_PIPES;
|
||||
#endif
|
||||
|
||||
ret = ipa_eth_client_reg_intf(&intf);
|
||||
if (ret) {
|
||||
IPA_UT_ERR("Failed to register IPA interface");
|
||||
}
|
||||
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
#else
|
||||
kfree(intf.pipe_hdl_list);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -721,13 +766,26 @@ static int ipa_ntn_test_reg_intf(void)
|
||||
static int ipa_ntn_test_unreg_intf(void)
|
||||
{
|
||||
struct ipa_eth_intf_info intf;
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
struct net_device dummy_net_dev;
|
||||
#else
|
||||
char netdev_name[IPA_RESOURCE_NAME_MAX] = { 0 };
|
||||
#endif
|
||||
|
||||
memset(&intf, 0, sizeof(intf));
|
||||
#if IPA_ETH_API_VER >= 2
|
||||
memset(dummy_net_dev.name, 0, sizeof(dummy_net_dev.name));
|
||||
|
||||
intf.net_dev = &dummy_net_dev;
|
||||
|
||||
snprintf(intf.net_dev->name, sizeof(intf.net_dev->name), "ntn_test");
|
||||
IPA_UT_INFO("netdev name: %s strlen: %lu\n", intf.net_dev->name, strlen(intf.net_dev->name));
|
||||
#else
|
||||
snprintf(netdev_name, sizeof(netdev_name), "ntn_test");
|
||||
intf.netdev_name = netdev_name;
|
||||
IPA_UT_INFO("netdev name: %s strlen: %lu\n", intf.netdev_name,
|
||||
strlen(intf.netdev_name));
|
||||
#endif
|
||||
|
||||
return (ipa_eth_client_unreg_intf(&intf));
|
||||
}
|
||||
@@ -810,7 +868,6 @@ static int ipa_ntn_send_one_packet(void)
|
||||
while ((orig_rx_tail == *rx_ring_tail) ||
|
||||
(orig_tx_tail == *tx_ring_tail)) {
|
||||
loop_cnt++;
|
||||
|
||||
if (loop_cnt == 1000) {
|
||||
IPA_UT_ERR("transfer timeout!\n");
|
||||
IPA_UT_ERR("orig_tx_tail: %X tx_ring_db: %X\n",
|
||||
@@ -957,11 +1014,11 @@ static int ipa_ntn_test_prepare_test(void)
|
||||
|
||||
/* configure NTN RX EP in DMA mode */
|
||||
ep_cfg.mode.mode = IPA_DMA;
|
||||
ep_cfg.mode.dst = IPA_CLIENT_ETHERNET_CONS;
|
||||
ep_cfg.mode.dst = test_ntn_ctx->cons_client_type;
|
||||
|
||||
ep_cfg.seq.set_dynamic = true;
|
||||
|
||||
if (ipa3_cfg_ep(ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_PROD),
|
||||
if (ipa3_cfg_ep(ipa_get_ep_mapping(test_ntn_ctx->prod_client_type),
|
||||
&ep_cfg)) {
|
||||
IPA_UT_ERR("fail to configure DMA mode.\n");
|
||||
ret = -EFAULT;
|
||||
@@ -1184,7 +1241,7 @@ static int ipa_ntn_send_packet_burst(void)
|
||||
*/
|
||||
ep_cfg_ctrl.ipa_ep_delay = true;
|
||||
ret = ipa3_cfg_ep_ctrl(
|
||||
ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_PROD),
|
||||
ipa_get_ep_mapping(test_ntn_ctx->prod_client_type),
|
||||
&ep_cfg_ctrl);
|
||||
if (ret) {
|
||||
IPA_UT_ERR("couldn't set delay to ETHERNET_PROD\n");
|
||||
@@ -1219,7 +1276,7 @@ static int ipa_ntn_send_packet_burst(void)
|
||||
msleep(20);
|
||||
ep_cfg_ctrl.ipa_ep_delay = false;
|
||||
ret = ipa3_cfg_ep_ctrl(
|
||||
ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_PROD),
|
||||
ipa_get_ep_mapping(test_ntn_ctx->prod_client_type),
|
||||
&ep_cfg_ctrl);
|
||||
if (ret) {
|
||||
IPA_UT_ERR("couldn't unset delay to ETHERNET_PROD\n");
|
||||
@@ -1374,6 +1431,17 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ipa_ntn_test_clients2_multi_transfer_burst(void *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ipa_test_ntn_set_client_params(IPA_CLIENT_ETHERNET2_CONS, IPA_CLIENT_ETHERNET2_PROD, 1);
|
||||
ret = ipa_ntn_test_multi_transfer_burst(priv);
|
||||
ipa_test_ntn_set_client_params(IPA_CLIENT_ETHERNET_CONS, IPA_CLIENT_ETHERNET_PROD, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Suite definition block */
|
||||
IPA_UT_DEFINE_SUITE_START(ntn, "NTN3 tests",
|
||||
ipa_test_ntn_suite_setup, ipa_test_ntn_suite_teardown)
|
||||
@@ -1402,6 +1470,11 @@ IPA_UT_DEFINE_SUITE_START(ntn, "NTN3 tests",
|
||||
"send entire ring in one shot",
|
||||
ipa_ntn_test_multi_transfer_burst,
|
||||
true, IPA_HW_v5_0, IPA_HW_MAX),
|
||||
|
||||
IPA_UT_ADD_TEST(clients2_multi_transfer_burst,
|
||||
"Clients pair 2 send entire ring in one shot",
|
||||
ipa_ntn_test_clients2_multi_transfer_burst,
|
||||
true, IPA_HW_v5_0, IPA_HW_MAX),
|
||||
} IPA_UT_DEFINE_SUITE_END(ntn);
|
||||
|
||||
|
||||
|
Odkázat v novém úkolu
Zablokovat Uživatele