Просмотр исходного кода

rmnet_core: segment ULSO skbs on LL channel

ULSO is not supported on the LL endpoint. If such skbs are received by the
rmnet driver, they must be segmented in software before transmitting them.

Change-Id: I0103d06c6bfa8eb96cfbde85f68b1b45034a93e5
Signed-off-by: Sean Tranchetti <[email protected]>
Sean Tranchetti 4 лет назад
Родитель
Сommit
42e9497010
2 измененных файлов с 26 добавлено и 1 удалено
  1. 2 0
      core/rmnet_config.h
  2. 24 1
      core/rmnet_vnd.c

+ 2 - 0
core/rmnet_config.h

@@ -188,6 +188,8 @@ struct rmnet_priv_stats {
 	u64 ul_prio;
 	u64 tso_pkts;
 	u64 tso_arriv_errs;
+	u64 ll_tso_segs;
+	u64 ll_tso_errs;
 };
 
 struct rmnet_priv {

+ 24 - 1
core/rmnet_vnd.c

@@ -89,7 +89,30 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb,
 			rmnet_perf_tether_egress(skb);
 		}
 		low_latency = qmi_rmnet_flow_is_low_latency(dev, skb);
-		rmnet_egress_handler(skb, low_latency);
+		if (low_latency && skb_is_gso(skb)) {
+			netdev_features_t features;
+			struct sk_buff *segs, *tmp;
+
+			features = dev->features & ~NETIF_F_GSO_MASK;
+			segs = skb_gso_segment(skb, features);
+			if (IS_ERR_OR_NULL(segs)) {
+				this_cpu_add(priv->pcpu_stats->stats.tx_drops,
+					     skb_shinfo(skb)->gso_segs);
+				priv->stats.ll_tso_errs++;
+				kfree_skb(skb);
+				return NETDEV_TX_OK;
+			}
+
+			consume_skb(skb);
+			for (skb = segs; skb; skb = tmp) {
+				tmp = skb->next;
+				skb->dev = dev;
+				priv->stats.ll_tso_segs++;
+				rmnet_egress_handler(skb, low_latency);
+			}
+		} else {
+			rmnet_egress_handler(skb, low_latency);
+		}
 		qmi_rmnet_burst_fc_check(dev, ip_type, mark, len);
 		qmi_rmnet_work_maybe_restart(rmnet_get_rmnet_port(dev));
 	} else {