diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index eef0782e98b1..e3569cf4d13e 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/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]; diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index 7c6c18fff2aa..09eef4789224 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/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 */ diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index 471f29eae0d6..2eac124b98c8 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/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 */ /** diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 8592bf5734d4..e7d24c79a359 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/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],