qcacmn: Add support for TCP delayed ack in driver

qcacld-2.0 to qcacmn propagation

This change adds support for driver supported TCP
delayed ack to increase TCP RX performance in
third-party platform which don't support kernel
TCP delayed ack feature.

TCP delayed ack is dependent on count and timer
values. Whatever is achieved first will trigger
sending TCP ack.

This feature can be controlled through ini values.
gDriverDelAckTimerValue - timer value in ms
gDriverDelAckPktCount - delayed ack count
gDriverDelAckEnable - enable/disable feature

Change-Id: I8105bbb90965295b5a4aefeb00d344a90155974d
CRs-fixed: 2414231
diff --git a/dp/inc/cdp_txrx_misc.h b/dp/inc/cdp_txrx_misc.h
index 77bcb6c..56c7224 100644
--- a/dp/inc/cdp_txrx_misc.h
+++ b/dp/inc/cdp_txrx_misc.h
@@ -620,4 +620,55 @@
 	if (soc->ops->misc_ops->unregister_pktdump_cb)
 		return soc->ops->misc_ops->unregister_pktdump_cb();
 }
+
+/**
+ * cdp_pdev_reset_driver_del_ack() - reset driver TCP delayed ack flag
+ * @soc - data path soc handle
+ * @pdev - data path device instance
+ *
+ * Return: none
+ */
+static inline void cdp_pdev_reset_driver_del_ack(void *psoc,
+						 struct cdp_pdev *pdev)
+{
+	ol_txrx_soc_handle soc = psoc;
+
+	if (!soc || !soc->ops || !soc->ops->misc_ops) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL,
+			  "%s invalid instance", __func__);
+		return;
+	}
+
+	if (soc->ops->misc_ops->pdev_reset_driver_del_ack)
+		return soc->ops->misc_ops->pdev_reset_driver_del_ack(pdev);
+}
+
+/*
+ * cdp_vdev_set_driver_del_ack_enable() - set driver delayed ack enabled flag
+ * @soc - data path soc handle
+ * @vdev_id: vdev id
+ * @rx_packets: number of rx packets
+ * @time_in_ms: time in ms
+ * @high_th: high threshold
+ * @low_th: low threshold
+ *
+ * Return: none
+ */
+static inline void cdp_vdev_set_driver_del_ack_enable(ol_txrx_soc_handle soc,
+						      uint8_t vdev_id,
+						      unsigned long rx_packets,
+						      uint32_t time_in_ms,
+						      uint32_t high_th,
+						      uint32_t low_th)
+{
+	if (!soc || !soc->ops || !soc->ops->misc_ops) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL,
+			  "%s invalid instance", __func__);
+		return;
+	}
+
+	if (soc->ops->misc_ops->vdev_set_driver_del_ack_enable)
+		return soc->ops->misc_ops->vdev_set_driver_del_ack_enable(
+			vdev_id, rx_packets, time_in_ms, high_th, low_th);
+}
 #endif /* _CDP_TXRX_MISC_H_ */
diff --git a/dp/inc/cdp_txrx_mob_def.h b/dp/inc/cdp_txrx_mob_def.h
index df69ee8..a997e48 100644
--- a/dp/inc/cdp_txrx_mob_def.h
+++ b/dp/inc/cdp_txrx_mob_def.h
@@ -291,6 +291,15 @@
 	/* Start queue offset in percentage */
 	uint32_t tx_flow_start_queue_offset;
 
+#ifdef QCA_SUPPORT_TXRX_DRIVER_TCP_DEL_ACK
+	/* enable the tcp delay ack feature in the driver */
+	bool  del_ack_enable;
+	/* timeout if no more tcp ack frames, unit is ms */
+	uint16_t del_ack_timer_value;
+	/* the maximum number of replaced tcp ack frames */
+	uint16_t del_ack_pkt_count;
+#endif
+
 	struct ol_tx_sched_wrr_ac_specs_t ac_specs[TX_WMM_AC_NUM];
 	bool gro_enable;
 	bool tso_enable;
diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h
index 546de5a..1ff0575 100644
--- a/dp/inc/cdp_txrx_ops.h
+++ b/dp/inc/cdp_txrx_ops.h
@@ -986,6 +986,8 @@
  * @runtime_resume:
  * @register_packetdump_cb:
  * @unregister_packetdump_cb:
+ * @pdev_reset_driver_del_ack:
+ * @vdev_set_driver_del_ack_enable:
  */
 struct cdp_misc_ops {
 	uint16_t (*set_ibss_vdev_heart_beat_timer)(struct cdp_vdev *vdev,
@@ -1023,6 +1025,12 @@
 	void (*register_pktdump_cb)(ol_txrx_pktdump_cb tx_cb,
 				    ol_txrx_pktdump_cb rx_cb);
 	void (*unregister_pktdump_cb)(void);
+	void (*pdev_reset_driver_del_ack)(struct cdp_pdev *ppdev);
+	void (*vdev_set_driver_del_ack_enable)(uint8_t vdev_id,
+					       unsigned long rx_packets,
+					       uint32_t time_in_ms,
+					       uint32_t high_th,
+					       uint32_t low_th);
 };
 
 /**
diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h
index 02c3ed8..372151c 100644
--- a/qdf/inc/qdf_nbuf.h
+++ b/qdf/inc/qdf_nbuf.h
@@ -44,6 +44,7 @@
 #define QDF_NBUF_PKT_ERROR			1
 
 #define QDF_NBUF_TRAC_IPV4_OFFSET		14
+#define QDF_NBUF_TRAC_IPV4_HEADER_MASK		0xF
 #define QDF_NBUF_TRAC_IPV4_HEADER_SIZE		20
 #define QDF_NBUF_TRAC_DHCP_SRV_PORT		67
 #define QDF_NBUF_TRAC_DHCP_CLI_PORT		68
@@ -60,6 +61,7 @@
 #define QDF_NBUF_SRC_MAC_OFFSET			6
 #define QDF_NBUF_TRAC_IPV4_PROTO_TYPE_OFFSET  23
 #define QDF_NBUF_TRAC_IPV4_DEST_ADDR_OFFSET   30
+#define QDF_NBUF_TRAC_IPV4_SRC_ADDR_OFFSET    26
 #define QDF_NBUF_TRAC_IPV6_PROTO_TYPE_OFFSET  20
 #define QDF_NBUF_TRAC_IPV4_ADDR_MCAST_MASK    0xE0000000
 #define QDF_NBUF_TRAC_IPV4_ADDR_BCAST_MASK    0xF0000000
@@ -69,6 +71,12 @@
 #define QDF_NBUF_TRAC_IPV6_HEADER_SIZE   40
 #define QDF_NBUF_TRAC_ICMP_TYPE         1
 #define QDF_NBUF_TRAC_TCP_TYPE          6
+#define QDF_NBUF_TRAC_TCP_FLAGS_OFFSET       (47 - 34)
+#define QDF_NBUF_TRAC_TCP_ACK_OFFSET         (42 - 34)
+#define QDF_NBUF_TRAC_TCP_HEADER_LEN_OFFSET  (46 - 34)
+#define QDF_NBUF_TRAC_TCP_ACK_MASK           0x10
+#define QDF_NBUF_TRAC_TCP_SPORT_OFFSET       (34 - 34)
+#define QDF_NBUF_TRAC_TCP_DPORT_OFFSET       (36 - 34)
 #define QDF_NBUF_TRAC_UDP_TYPE          17
 #define QDF_NBUF_TRAC_ICMPV6_TYPE       0x3a
 #define QDF_NBUF_TRAC_DHCP6_SRV_PORT		547
diff --git a/qdf/linux/src/i_qdf_hrtimer.h b/qdf/linux/src/i_qdf_hrtimer.h
index 6c6b6d5..d72db57 100644
--- a/qdf/linux/src/i_qdf_hrtimer.h
+++ b/qdf/linux/src/i_qdf_hrtimer.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -40,6 +40,20 @@
 } __qdf_hrtimer_data_t;
 
 /**
+ * __qdf_hrtimer_get_mode() - Get hrtimer_mode with qdf mode
+ * @mode: mode of hrtimer
+ *
+ * Get hrtimer_mode with qdf hrtimer mode
+ *
+ * Return: void
+ */
+static inline
+enum hrtimer_mode __qdf_hrtimer_get_mode(enum qdf_hrtimer_mode mode)
+{
+	return (enum hrtimer_mode)mode;
+}
+
+/**
  * __qdf_hrtimer_start() - Starts hrtimer in given context
  * @timer: pointer to the hrtimer object
  * @interval: interval to forward as qdf_ktime_t object
@@ -53,11 +67,13 @@
 void __qdf_hrtimer_start(__qdf_hrtimer_data_t *timer, ktime_t interval,
 			 enum qdf_hrtimer_mode mode)
 {
+	enum hrtimer_mode hrt_mode = __qdf_hrtimer_get_mode(mode);
+
 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
-		hrtimer_start(&timer->u.hrtimer, interval, mode);
+		hrtimer_start(&timer->u.hrtimer, interval, hrt_mode);
 	else if (timer->ctx == QDF_CONTEXT_TASKLET)
 		tasklet_hrtimer_start(&timer->u.tasklet_hrtimer,
-				      interval, mode);
+				      interval, hrt_mode);
 }
 
 /**
@@ -98,14 +114,15 @@
 {
 	struct hrtimer *hrtimer = &timer->u.hrtimer;
 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
+	enum hrtimer_mode hrt_mode = __qdf_hrtimer_get_mode(mode);
 
 	timer->ctx = ctx;
 
 	if (timer->ctx == QDF_CONTEXT_HARDWARE) {
-		hrtimer_init(hrtimer, clock, mode);
+		hrtimer_init(hrtimer, clock, hrt_mode);
 		hrtimer->function = cback;
 	} else if (timer->ctx == QDF_CONTEXT_TASKLET) {
-		tasklet_hrtimer_init(tasklet_hrtimer, cback, clock, mode);
+		tasklet_hrtimer_init(tasklet_hrtimer, cback, clock, hrt_mode);
 	}
 }