mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-14 16:46:15 -04:00
Merge b8fea6fab4 on remote branch
Change-Id: I5cbed2a7df439cbffb10aedb7ea889e2cf9608bc
This commit is contained in:
commit
a697338671
4 changed files with 49 additions and 7 deletions
|
|
@ -1253,7 +1253,7 @@ void qmi_rmnet_work_init(void *port)
|
|||
return;
|
||||
|
||||
rmnet_ps_wq = alloc_workqueue("rmnet_powersave_work",
|
||||
WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE, 1);
|
||||
WQ_CPU_INTENSIVE, 1);
|
||||
|
||||
if (!rmnet_ps_wq)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -849,6 +849,16 @@ skip_frags:
|
|||
th->seq = frag_desc->tcp_seq;
|
||||
}
|
||||
|
||||
if (frag_desc->tcp_flags_set) {
|
||||
struct tcphdr *th;
|
||||
__be16 *flags;
|
||||
|
||||
th = (struct tcphdr *)
|
||||
(rmnet_map_data_ptr(head_skb) + frag_desc->ip_len);
|
||||
flags = (__be16 *)&tcp_flag_word(th);
|
||||
*flags = frag_desc->tcp_flags;
|
||||
}
|
||||
|
||||
/* Handle csum offloading */
|
||||
if (frag_desc->csum_valid && frag_desc->hdrs_valid) {
|
||||
/* Set the partial checksum information */
|
||||
|
|
@ -984,6 +994,24 @@ static void __rmnet_frag_segment_data(struct rmnet_frag_descriptor *coal_desc,
|
|||
new_desc->tcp_seq_set = 1;
|
||||
new_desc->tcp_seq = htonl(ntohl(th->seq) +
|
||||
coal_desc->data_offset);
|
||||
|
||||
/* Don't allow any dangerous flags to appear in any segments
|
||||
* other than the last.
|
||||
*/
|
||||
if (th->fin || th->psh) {
|
||||
if (offset + dlen < coal_desc->len) {
|
||||
__be32 flag_word = tcp_flag_word(th);
|
||||
|
||||
/* Clear the FIN and PSH flags from this
|
||||
* segment.
|
||||
*/
|
||||
flag_word &= ~TCP_FLAG_FIN;
|
||||
flag_word &= ~TCP_FLAG_PSH;
|
||||
|
||||
new_desc->tcp_flags_set = 1;
|
||||
new_desc->tcp_flags = *((__be16 *)&flag_word);
|
||||
}
|
||||
}
|
||||
} else if (coal_desc->trans_proto == IPPROTO_UDP) {
|
||||
struct udphdr *uh, __uh;
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ struct rmnet_frag_descriptor {
|
|||
u32 hash;
|
||||
__be32 tcp_seq;
|
||||
__be16 ip_id;
|
||||
__be16 tcp_flags;
|
||||
u16 data_offset;
|
||||
u16 gso_size;
|
||||
u16 gso_segs;
|
||||
|
|
@ -53,7 +54,8 @@ struct rmnet_frag_descriptor {
|
|||
ip_id_set:1,
|
||||
tcp_seq_set:1,
|
||||
flush_shs:1,
|
||||
reserved:3;
|
||||
tcp_flags_set:1,
|
||||
reserved:2;
|
||||
};
|
||||
|
||||
/* Descriptor management */
|
||||
|
|
|
|||
|
|
@ -744,22 +744,23 @@ __rmnet_map_segment_coal_skb(struct sk_buff *coal_skb,
|
|||
struct rmnet_priv *priv = netdev_priv(coal_skb->dev);
|
||||
__sum16 *check = NULL;
|
||||
u32 alloc_len;
|
||||
u32 dlen = coal_meta->data_len * coal_meta->pkt_count;
|
||||
u32 hlen = coal_meta->ip_len + coal_meta->trans_len;
|
||||
bool zero_csum = false;
|
||||
|
||||
/* We can avoid copying the data if the SKB we got from the lower-level
|
||||
* drivers was nonlinear.
|
||||
*/
|
||||
if (skb_is_nonlinear(coal_skb))
|
||||
alloc_len = coal_meta->ip_len + coal_meta->trans_len;
|
||||
alloc_len = hlen;
|
||||
else
|
||||
alloc_len = coal_meta->ip_len + coal_meta->trans_len +
|
||||
(coal_meta->data_len * coal_meta->pkt_count);
|
||||
alloc_len = hlen + dlen;
|
||||
|
||||
skbn = alloc_skb(alloc_len, GFP_ATOMIC);
|
||||
if (!skbn)
|
||||
return;
|
||||
|
||||
skb_reserve(skbn, coal_meta->ip_len + coal_meta->trans_len);
|
||||
skb_reserve(skbn, hlen);
|
||||
rmnet_map_nonlinear_copy(coal_skb, coal_meta, skbn);
|
||||
|
||||
/* Push transport header and update necessary fields */
|
||||
|
|
@ -771,6 +772,17 @@ __rmnet_map_segment_coal_skb(struct sk_buff *coal_skb,
|
|||
|
||||
th->seq = htonl(ntohl(th->seq) + coal_meta->data_offset);
|
||||
check = &th->check;
|
||||
|
||||
/* Don't allow dangerous flags to be set in any segment but the
|
||||
* last one.
|
||||
*/
|
||||
if (th->fin || th->psh) {
|
||||
if (hlen + coal_meta->data_offset + dlen <
|
||||
coal_skb->len) {
|
||||
th->fin = 0;
|
||||
th->psh = 0;
|
||||
}
|
||||
}
|
||||
} else if (coal_meta->trans_proto == IPPROTO_UDP) {
|
||||
struct udphdr *uh = udp_hdr(skbn);
|
||||
|
||||
|
|
@ -846,7 +858,7 @@ __rmnet_map_segment_coal_skb(struct sk_buff *coal_skb,
|
|||
__skb_queue_tail(list, skbn);
|
||||
|
||||
/* Update meta information to move past the data we just segmented */
|
||||
coal_meta->data_offset += coal_meta->data_len * coal_meta->pkt_count;
|
||||
coal_meta->data_offset += dlen;
|
||||
coal_meta->pkt_id = pkt_id + 1;
|
||||
coal_meta->pkt_count = 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue