Loading core/qmi_rmnet.c +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading core/rmnet_descriptor.c +28 −0 Original line number Diff line number Diff line Loading @@ -849,6 +849,16 @@ static struct sk_buff *rmnet_alloc_skb(struct rmnet_frag_descriptor *frag_desc, 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 */ Loading Loading @@ -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; Loading core/rmnet_descriptor.h +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 */ Loading core/rmnet_map_data.c +17 −5 Original line number Diff line number Diff line Loading @@ -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 */ Loading @@ -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); Loading Loading @@ -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 Loading
core/qmi_rmnet.c +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
core/rmnet_descriptor.c +28 −0 Original line number Diff line number Diff line Loading @@ -849,6 +849,16 @@ static struct sk_buff *rmnet_alloc_skb(struct rmnet_frag_descriptor *frag_desc, 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 */ Loading Loading @@ -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; Loading
core/rmnet_descriptor.h +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 */ Loading
core/rmnet_map_data.c +17 −5 Original line number Diff line number Diff line Loading @@ -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 */ Loading @@ -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); Loading Loading @@ -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