Blob Blame History Raw
From: Julian Wiedmann <jwi@linux.ibm.com>
Subject: s390/qeth: try harder to get packets from RX buffer
Patch-mainline: v4.15-rc1
Git-commit: 864c17c3d83be6a1f6a2888566e93e114986abca
References: FATE#326350, LTC#169511, bsc#1113509

Summary:     qeth: performance improvements
Description: This adds recent functional and performance improvements for the
             qeth network driver.
             Primarily this brings Scatter-Gather support for HiperSockets,
             reduced CPU consumption in the L3 IPv4 transmit path for OSA,
             improved Promiscuous Mode performance due to IFF_UNICAST_FLT,
             support for Scatter-Gather on z/VM virtual NICs, and
             support for delayed GRO flushing.

             For sanity & stability reasons, this effectively constitutes a
             backport of the qeth device driver from 4.19 mainline.
             

Upstream-Description:

             s390/qeth: try harder to get packets from RX buffer

             Current code bails out when two subsequent buffer elements hold
             insufficient data to contain a qeth_hdr packet descriptor.
             This seems reasonable, but it would be legal for quirky hardware to
             leave a few elements empty and then present packets in a subsequent
             element. These packets would currently be dropped.

             So make sure to check all buffer elements, until we hit the LAST_ENTRY
             indication.

             Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com>
             Signed-off-by: David S. Miller <davem@davemloft.net>

Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/s390/net/qeth_core_main.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -5231,13 +5231,11 @@ struct sk_buff *qeth_core_get_next_skb(s
 	int use_rx_sg = 0;
 
 	/* qeth_hdr must not cross element boundaries */
-	if (element->length < offset + sizeof(struct qeth_hdr)) {
+	while (element->length < offset + sizeof(struct qeth_hdr)) {
 		if (qeth_is_last_sbale(element))
 			return NULL;
 		element++;
 		offset = 0;
-		if (element->length < sizeof(struct qeth_hdr))
-			return NULL;
 	}
 	*hdr = element->addr + offset;