浏览代码

rmnet_core: packets prioritization

Low latency treatment of UL packets based on priority.

Change-Id: Id7a7d990f05923aacb50901c0e09194155a3edf2
Signed-off-by: Weiyi Chen <[email protected]>
Weiyi Chen 3 年之前
父节点
当前提交
5eb9a7affc
共有 4 个文件被更改,包括 47 次插入7 次删除
  1. 14 0
      core/rmnet_config.h
  2. 3 1
      core/rmnet_map.h
  3. 14 5
      core/rmnet_map_data.c
  4. 16 1
      core/rmnet_vnd.c

+ 14 - 0
core/rmnet_config.h

@@ -1,4 +1,5 @@
 /* Copyright (c) 2013-2014, 2016-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -26,6 +27,18 @@
 #define RMNET_SHS_NO_PSH BIT(1)
 #define RMNET_SHS_NO_DLMKR BIT(2)
 
+#define RMNET_LLM(prio) ((prio) == 0xDA001A) /* qmipriod */
+
+#define RMNET_APS_MAJOR 0x9B6D
+#define RMNET_APS_LLC_MASK 0x0100
+#define RMNET_APS_LLB_MASK 0x0200
+
+#define RMNET_APS_LLC(prio) \
+	(((prio) >> 16 == RMNET_APS_MAJOR) && ((prio) & RMNET_APS_LLC_MASK))
+
+#define RMNET_APS_LLB(prio) \
+        (((prio) >> 16 == RMNET_APS_MAJOR) && ((prio) & RMNET_APS_LLB_MASK))
+
 struct rmnet_shs_clnt_s {
 	u16 config;
 	u16 map_mask;
@@ -196,6 +209,7 @@ struct rmnet_priv_stats {
 	u64 tso_segment_skip;
 	u64 ll_tso_segs;
 	u64 ll_tso_errs;
+	u64 aps_prio;
 };
 
 struct rmnet_priv {

+ 3 - 1
core/rmnet_map.h

@@ -1,4 +1,5 @@
 /* Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -81,7 +82,8 @@ struct rmnet_map_header {
 struct rmnet_map_v5_csum_header {
 	u8  next_hdr:1;
 	u8  header_type:7;
-	u8  hw_reserved:5;
+	u8  hw_reserved:4;
+	u8  aps_prio:1;
 	u8  priority:1;
 	u8  hw_reserved_bit:1;
 	u8  csum_valid_required:1;

+ 14 - 5
core/rmnet_map_data.c

@@ -1,4 +1,5 @@
 /* Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -493,14 +494,21 @@ sw_csum:
 
 static void rmnet_map_v5_check_priority(struct sk_buff *skb,
 					struct net_device *orig_dev,
-					struct rmnet_map_v5_csum_header *hdr)
+					struct rmnet_map_v5_csum_header *hdr,
+					bool tso)
 {
 	struct rmnet_priv *priv = netdev_priv(orig_dev);
 
-	if (skb->priority) {
+	if (RMNET_LLM(skb->priority)) {
 		priv->stats.ul_prio++;
 		hdr->priority = 1;
 	}
+
+	/* APS priority bit is only valid for csum header */
+	if (!tso && RMNET_APS_LLB(skb->priority)) {
+		priv->stats.aps_prio++;
+		hdr->aps_prio = 1;
+	}
 }
 
 void rmnet_map_v5_checksum_uplink_packet(struct sk_buff *skb,
@@ -516,7 +524,7 @@ void rmnet_map_v5_checksum_uplink_packet(struct sk_buff *skb,
 	ul_header->header_type = RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD;
 
 	if (port->data_format & RMNET_EGRESS_FORMAT_PRIORITY)
-		rmnet_map_v5_check_priority(skb, orig_dev, ul_header);
+		rmnet_map_v5_check_priority(skb, orig_dev, ul_header, false);
 
 	/* Allow priority w/o csum offload */
 	if (!(port->data_format & RMNET_PRIV_FLAGS_EGRESS_MAP_CKSUMV5))
@@ -1468,7 +1476,7 @@ new_packet:
 	ktime_get_real_ts64(&state->agg_last);
 
 	if ((port->data_format & RMNET_EGRESS_FORMAT_PRIORITY) &&
-	    skb->priority) {
+	    (RMNET_LLM(skb->priority) || RMNET_APS_LLB(skb->priority))) {
 		/* Send out any aggregated SKBs we have */
 		rmnet_map_send_agg_skb(state, flags);
 		/* Send out the priority SKB. Not holding agg_lock anymore */
@@ -1690,7 +1698,8 @@ int rmnet_map_add_tso_header(struct sk_buff *skb, struct rmnet_port *port,
 
 	if (port->data_format & RMNET_EGRESS_FORMAT_PRIORITY)
 		rmnet_map_v5_check_priority(skb, orig_dev,
-					    (struct rmnet_map_v5_csum_header *)ul_header);
+					    (struct rmnet_map_v5_csum_header *)ul_header,
+					    true);
 
 	ul_header->segment_size = htons(skb_shinfo(skb)->gso_size);
 

+ 16 - 1
core/rmnet_vnd.c

@@ -106,7 +106,11 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb,
 			return NETDEV_TX_OK;
 		}
 
-		if (low_latency && skb_is_gso(skb)) {
+		if (RMNET_APS_LLC(skb->priority))
+			low_latency = true;
+
+		if ((low_latency || RMNET_APS_LLB(skb->priority)) &&
+		    skb_is_gso(skb)) {
 			netdev_features_t features;
 			struct sk_buff *segs, *tmp;
 
@@ -257,6 +261,9 @@ static void rmnet_get_stats64(struct net_device *dev,
 	s->tx_dropped = total_stats.tx_drops;
 }
 
+void (*rmnet_aps_set_prio)(struct net_device *dev, struct sk_buff *skb);
+EXPORT_SYMBOL(rmnet_aps_set_prio);
+
 static u16 rmnet_vnd_select_queue(struct net_device *dev,
 				  struct sk_buff *skb,
 				  struct net_device *sb_dev)
@@ -266,6 +273,7 @@ static u16 rmnet_vnd_select_queue(struct net_device *dev,
 	int boost_trigger = 0;
 	int txq = 0;
 	rmnet_perf_egress_hook1_t rmnet_perf_egress1;
+	void (*aps_set_prio)(struct net_device *dev, struct sk_buff *skb);
 
 	rmnet_perf_egress1 = rcu_dereference(rmnet_perf_egress_hook1);
 	if (rmnet_perf_egress1) {
@@ -428,6 +436,12 @@ skip_trace:
 			(void) boost_period;
 	}
 
+	rcu_read_lock();
+	aps_set_prio = READ_ONCE(rmnet_aps_set_prio);
+	if (aps_set_prio)
+		aps_set_prio(dev, skb);
+	rcu_read_unlock();
+
 	return (txq < dev->real_num_tx_queues) ? txq : 0;
 }
 
@@ -487,6 +501,7 @@ static const char rmnet_gstrings_stats[][ETH_GSTRING_LEN] = {
 	"TSO segment skip",
 	"LL TSO segment success",
 	"LL TSO segment fail",
+	"APS priority packets",
 };
 
 static const char rmnet_port_gstrings_stats[][ETH_GSTRING_LEN] = {