Merge "msm: ipa3: linearize large skbs"
This commit is contained in:
commit
a708ddf420
1 changed files with 37 additions and 22 deletions
|
@ -1723,6 +1723,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
|
||||||
struct ipa3_sys_context *sys;
|
struct ipa3_sys_context *sys;
|
||||||
int src_ep_idx;
|
int src_ep_idx;
|
||||||
int num_frags, f;
|
int num_frags, f;
|
||||||
|
struct ipa_gsi_ep_config *gsi_ep;
|
||||||
|
|
||||||
if (unlikely(!ipa3_ctx)) {
|
if (unlikely(!ipa3_ctx)) {
|
||||||
IPAERR("IPA3 driver was not initialized\n");
|
IPAERR("IPA3 driver was not initialized\n");
|
||||||
|
@ -1734,23 +1735,6 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_frags = skb_shinfo(skb)->nr_frags;
|
|
||||||
if (num_frags) {
|
|
||||||
/* 1 desc for tag to resolve status out-of-order issue;
|
|
||||||
* 1 desc is needed for the linear portion of skb;
|
|
||||||
* 1 desc may be needed for the PACKET_INIT;
|
|
||||||
* 1 desc for each frag
|
|
||||||
*/
|
|
||||||
desc = kzalloc(sizeof(*desc) * (num_frags + 3), GFP_ATOMIC);
|
|
||||||
if (!desc) {
|
|
||||||
IPAERR("failed to alloc desc array\n");
|
|
||||||
goto fail_mem;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
memset(_desc, 0, 3 * sizeof(struct ipa3_desc));
|
|
||||||
desc = &_desc[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* USB_CONS: PKT_INIT ep_idx = dst pipe
|
* USB_CONS: PKT_INIT ep_idx = dst pipe
|
||||||
* Q6_CONS: PKT_INIT ep_idx = sender pipe
|
* Q6_CONS: PKT_INIT ep_idx = sender pipe
|
||||||
|
@ -1787,6 +1771,37 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
|
||||||
goto fail_gen;
|
goto fail_gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
num_frags = skb_shinfo(skb)->nr_frags;
|
||||||
|
/*
|
||||||
|
* make sure TLV FIFO supports the needed frags.
|
||||||
|
* 2 descriptors are needed for IP_PACKET_INIT and TAG_STATUS.
|
||||||
|
* 1 descriptor needed for the linear portion of skb.
|
||||||
|
*/
|
||||||
|
gsi_ep = ipa3_get_gsi_ep_info(src_ep_idx);
|
||||||
|
if (gsi_ep && (num_frags + 3 > gsi_ep->ipa_if_tlv)) {
|
||||||
|
if (skb_linearize(skb)) {
|
||||||
|
IPAERR("Failed to linear skb with %d frags\n",
|
||||||
|
num_frags);
|
||||||
|
goto fail_gen;
|
||||||
|
}
|
||||||
|
num_frags = 0;
|
||||||
|
}
|
||||||
|
if (num_frags) {
|
||||||
|
/* 1 desc for tag to resolve status out-of-order issue;
|
||||||
|
* 1 desc is needed for the linear portion of skb;
|
||||||
|
* 1 desc may be needed for the PACKET_INIT;
|
||||||
|
* 1 desc for each frag
|
||||||
|
*/
|
||||||
|
desc = kzalloc(sizeof(*desc) * (num_frags + 3), GFP_ATOMIC);
|
||||||
|
if (!desc) {
|
||||||
|
IPAERR("failed to alloc desc array\n");
|
||||||
|
goto fail_gen;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memset(_desc, 0, 3 * sizeof(struct ipa3_desc));
|
||||||
|
desc = &_desc[0];
|
||||||
|
}
|
||||||
|
|
||||||
if (dst_ep_idx != -1) {
|
if (dst_ep_idx != -1) {
|
||||||
/* SW data path */
|
/* SW data path */
|
||||||
cmd.destination_pipe_index = dst_ep_idx;
|
cmd.destination_pipe_index = dst_ep_idx;
|
||||||
|
@ -1794,7 +1809,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
|
||||||
IPA_IMM_CMD_IP_PACKET_INIT, &cmd, true);
|
IPA_IMM_CMD_IP_PACKET_INIT, &cmd, true);
|
||||||
if (unlikely(!cmd_pyld)) {
|
if (unlikely(!cmd_pyld)) {
|
||||||
IPAERR("failed to construct ip_packet_init imm cmd\n");
|
IPAERR("failed to construct ip_packet_init imm cmd\n");
|
||||||
goto fail_gen;
|
goto fail_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the tag field will be populated in ipa3_send() function */
|
/* the tag field will be populated in ipa3_send() function */
|
||||||
|
@ -1863,7 +1878,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
|
||||||
if (num_frags == 0) {
|
if (num_frags == 0) {
|
||||||
if (ipa3_send(sys, 2, desc, true)) {
|
if (ipa3_send(sys, 2, desc, true)) {
|
||||||
IPAERR("fail to send skb %p HWP\n", skb);
|
IPAERR("fail to send skb %p HWP\n", skb);
|
||||||
goto fail_gen;
|
goto fail_mem;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (f = 0; f < num_frags; f++) {
|
for (f = 0; f < num_frags; f++) {
|
||||||
|
@ -1880,7 +1895,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
|
||||||
if (ipa3_send(sys, num_frags + 2, desc, true)) {
|
if (ipa3_send(sys, num_frags + 2, desc, true)) {
|
||||||
IPAERR("fail to send skb %p num_frags %u HWP\n",
|
IPAERR("fail to send skb %p num_frags %u HWP\n",
|
||||||
skb, num_frags);
|
skb, num_frags);
|
||||||
goto fail_gen;
|
goto fail_mem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IPA_STATS_INC_CNT(ipa3_ctx->stats.tx_hw_pkts);
|
IPA_STATS_INC_CNT(ipa3_ctx->stats.tx_hw_pkts);
|
||||||
|
@ -1894,10 +1909,10 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
|
||||||
|
|
||||||
fail_send:
|
fail_send:
|
||||||
ipahal_destroy_imm_cmd(cmd_pyld);
|
ipahal_destroy_imm_cmd(cmd_pyld);
|
||||||
fail_gen:
|
fail_mem:
|
||||||
if (num_frags)
|
if (num_frags)
|
||||||
kfree(desc);
|
kfree(desc);
|
||||||
fail_mem:
|
fail_gen:
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue