Browse Source

qcacld-3.0: Improve TX throughput for UDP apps with small buffers

Currently, in case the application send buffer size is very small (< 64k),
the application TX throughput is limited by its send buffer
(sk->sk_sndbuf). Once the send buffer is full (sk->sk_wmem_alloc
becomes greater or equal to sk->sk_sndbuf), the application can send
more data only when TX completions have arrived for some of the buffers
in the send buffer and some space is created.

Allow application(s) to send as much data over the wlan interface as
they may have, limited by the capability of the driver. Since the
driver has a limited number of TX descriptors, the maximum amount of
outstanding TX buffers are limited by the maximum number of TX
descriptors for that interface. For example, if the number of TX
descriptors for wlan0 are 1200, there can be at max 1200 (MSDU sized) TX packets.

Change-Id: I75eca2f4e10ecde1a5b347a305e896ac17d4ef7c
CRs-Fixed: 2016357
Mohit Khanna 8 years ago
parent
commit
d0b63f5e47

+ 2 - 2
core/hdd/inc/wlan_hdd_main.h

@@ -358,10 +358,10 @@ typedef struct hdd_tx_rx_stats_s {
 	/* start_xmit stats */
 	__u32    txXmitCalled;
 	__u32    txXmitDropped;
+	__u32    txXmitOrphaned;
 	__u32    txXmitClassifiedAC[NUM_TX_QUEUES];
 	__u32    txXmitDroppedAC[NUM_TX_QUEUES];
-	/* complete_cbk_stats */
-	__u32    txCompleted;
+
 	/* rx stats */
 	__u32 rxPackets[NUM_CPUS];
 	__u32 rxDropped[NUM_CPUS];

+ 22 - 4
core/hdd/src/wlan_hdd_softap_tx_rx.c

@@ -213,11 +213,29 @@ static inline struct sk_buff *hdd_skb_orphan(hdd_adapter_t *pAdapter,
 }
 
 #else
+/**
+ * hdd_skb_orphan() - skb_unshare a cloned packed else skb_orphan
+ * @pAdapter: pointer to HDD adapter
+ * @skb: pointer to skb data packet
+ *
+ * Return: pointer to skb structure
+ */
+static struct sk_buff *hdd_skb_orphan(hdd_adapter_t *pAdapter,
+		struct sk_buff *skb) {
 
-static inline struct sk_buff *hdd_skb_orphan(hdd_adapter_t *pAdapter,
-		struct sk_buff *skb)
-{
-	return skb_unshare(skb, GFP_ATOMIC);
+	struct sk_buff *nskb;
+	nskb = skb_unshare(skb, GFP_ATOMIC);
+
+	if (nskb == skb) {
+		/*
+		 * For UDP packets we want to orphan the packet to allow the app
+		 * to send more packets. The flow would ultimately be controlled
+		 * by the limited number of tx descriptors for the vdev.
+		 */
+		++pAdapter->hdd_stats.hddTxRxStats.txXmitOrphaned;
+		skb_orphan(skb);
+	}
+	return nskb;
 }
 #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
 

+ 22 - 5
core/hdd/src/wlan_hdd_tx_rx.c

@@ -282,13 +282,30 @@ void hdd_get_tx_resource(hdd_adapter_t *adapter,
 }
 
 #else
+/**
+ * hdd_skb_orphan() - skb_unshare a cloned packed else skb_orphan
+ * @pAdapter: pointer to HDD adapter
+ * @skb: pointer to skb data packet
+ *
+ * Return: pointer to skb structure
+ */
+static struct sk_buff *hdd_skb_orphan(hdd_adapter_t *pAdapter,
+		struct sk_buff *skb) {
 
-static inline struct sk_buff *hdd_skb_orphan(hdd_adapter_t *pAdapter,
-		struct sk_buff *skb)
-{
-	return skb_unshare(skb, GFP_ATOMIC);
-}
+	struct sk_buff *nskb;
+	nskb = skb_unshare(skb, GFP_ATOMIC);
 
+	if (nskb == skb) {
+		/*
+		 * For UDP packets we want to orphan the packet to allow the app
+		 * to send more packets. The flow would ultimately be controlled
+		 * by the limited number of tx descriptors for the vdev.
+		 */
+		++pAdapter->hdd_stats.hddTxRxStats.txXmitOrphaned;
+		skb_orphan(skb);
+	}
+	return nskb;
+}
 #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
 
 /**

+ 2 - 1
core/hdd/src/wlan_hdd_wext.c

@@ -2932,7 +2932,7 @@ void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, uint16_t *length,
 
 	len = scnprintf(buffer, buf_len,
 		"\nTransmit[%lu] - "
-		"called %u, dropped %u,"
+		"called %u, dropped %u orphan %u,"
 		"\n[dropped]    BK %u, BE %u, VI %u, VO %u"
 		"\n[classified] BK %u, BE %u, VI %u, VO %u"
 		"\n\nReceive[%lu] - "
@@ -2941,6 +2941,7 @@ void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, uint16_t *length,
 		qdf_system_ticks(),
 		pStats->txXmitCalled,
 		pStats->txXmitDropped,
+		pStats->txXmitOrphaned,
 
 		pStats->txXmitDroppedAC[SME_AC_BK],
 		pStats->txXmitDroppedAC[SME_AC_BE],