From 8804f978eb51d2a45a08d8562fcd5881eb60daec Mon Sep 17 00:00:00 2001 From: Manjunathappa Prakash Date: Wed, 12 Apr 2017 18:32:39 -0700 Subject: [PATCH] qcacmn: Do not LRO aggregate if peer is not connected We have race condition between lro flush of hif_napi_poll and MC thread lro flush while flushing the ol_txrx_cached_bufq packets for peer. Avoid the situation by simply marking the all the Rx packets as LRO ineligible while enqueuing packets to ol_rx_cached_buf. Change-Id: Ief0d7dd6c25cf45912820f0e237fd1179a57a5c7 CRs-Fixed: 2032674 --- qdf/linux/src/i_qdf_nbuf.h | 3 +++ qdf/linux/src/qdf_lro.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h index 8f8c9d715fb8..e432ead8381f 100644 --- a/qdf/linux/src/i_qdf_nbuf.h +++ b/qdf/linux/src/i_qdf_nbuf.h @@ -137,6 +137,7 @@ struct qdf_nbuf_cb { /* Note: MAX: 40 bytes */ struct { uint32_t lro_eligible:1, + no_peer_lro_ineligible:1, tcp_proto:1, tcp_pure_ack:1, ipv6_proto:1, @@ -251,6 +252,8 @@ QDF_COMPILE_TIME_ASSERT(qdf_nbuf_cb_size, #define QDF_NBUF_CB_RX_LRO_ELIGIBLE(skb) \ (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.lro_eligible) +#define QDF_NBUF_CB_RX_LRO_INELIGIBLE(skb) \ + (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.no_peer_lro_ineligible) #define QDF_NBUF_CB_RX_LRO_DESC(skb) \ (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.lro_desc) #define QDF_NBUF_CB_RX_LRO_CTX(skb) \ diff --git a/qdf/linux/src/qdf_lro.c b/qdf/linux/src/qdf_lro.c index a3ab6abedd14..5437c8993d84 100644 --- a/qdf/linux/src/qdf_lro.c +++ b/qdf/linux/src/qdf_lro.c @@ -328,6 +328,7 @@ bool qdf_lro_get_info(qdf_lro_ctx_t lro_ctx, qdf_nbuf_t nbuf, int hw_lro_eligible = QDF_NBUF_CB_RX_LRO_ELIGIBLE(nbuf) && (!QDF_NBUF_CB_RX_TCP_PURE_ACK(nbuf)); + int rx_data_before_peer_rx = QDF_NBUF_CB_RX_LRO_INELIGIBLE(nbuf); if (unlikely(!lro_ctx)) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, @@ -335,7 +336,7 @@ bool qdf_lro_get_info(qdf_lro_ctx_t lro_ctx, qdf_nbuf_t nbuf, return false; } - if (!hw_lro_eligible) + if (!hw_lro_eligible || rx_data_before_peer_rx) return false; iph = (struct iphdr *)info->iph;