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;
|
||||
int src_ep_idx;
|
||||
int num_frags, f;
|
||||
struct ipa_gsi_ep_config *gsi_ep;
|
||||
|
||||
if (unlikely(!ipa3_ctx)) {
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
* 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
/* SW data path */
|
||||
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);
|
||||
if (unlikely(!cmd_pyld)) {
|
||||
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 */
|
||||
|
@ -1863,7 +1878,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
|
|||
if (num_frags == 0) {
|
||||
if (ipa3_send(sys, 2, desc, true)) {
|
||||
IPAERR("fail to send skb %p HWP\n", skb);
|
||||
goto fail_gen;
|
||||
goto fail_mem;
|
||||
}
|
||||
} else {
|
||||
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)) {
|
||||
IPAERR("fail to send skb %p num_frags %u HWP\n",
|
||||
skb, num_frags);
|
||||
goto fail_gen;
|
||||
goto fail_mem;
|
||||
}
|
||||
}
|
||||
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:
|
||||
ipahal_destroy_imm_cmd(cmd_pyld);
|
||||
fail_gen:
|
||||
fail_mem:
|
||||
if (num_frags)
|
||||
kfree(desc);
|
||||
fail_mem:
|
||||
fail_gen:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue