sis900: fix TX completion
authorSergej Benilov <sergej.benilov@googlemail.com>
Thu, 20 Jun 2019 09:02:18 +0000 (11:02 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 21 Jul 2019 07:03:07 +0000 (09:03 +0200)
[ Upstream commit 8ac8a01092b2added0749ef937037bf1912e13e3 ]

Since commit 605ad7f184b60cfaacbc038aa6c55ee68dee3c89 "tcp: refine TSO autosizing",
outbound throughput is dramatically reduced for some connections, as sis900
is doing TX completion within idle states only.

Make TX completion happen after every transmitted packet.

Test:
netperf

before patch:
> netperf -H remote -l -2000000 -- -s 1000000
MIGRATED TCP STREAM TEST from 0.0.0.0 () port 0 AF_INET to 95.223.112.76 () port 0 AF_INET : demo
Recv   Send    Send
Socket Socket  Message  Elapsed
Size   Size    Size     Time     Throughput
bytes  bytes   bytes    secs.    10^6bits/sec

 87380 327680 327680    253.44      0.06

after patch:
> netperf -H remote -l -10000000 -- -s 1000000
MIGRATED TCP STREAM TEST from 0.0.0.0 () port 0 AF_INET to 95.223.112.76 () port 0 AF_INET : demo
Recv   Send    Send
Socket Socket  Message  Elapsed
Size   Size    Size     Time     Throughput
bytes  bytes   bytes    secs.    10^6bits/sec

 87380 327680 327680    5.38       14.89

Thx to Dave Miller and Eric Dumazet for helpful hints

Signed-off-by: Sergej Benilov <sergej.benilov@googlemail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/sis/sis900.c

index 4bb89f7..d5bcbc4 100644 (file)
@@ -1057,7 +1057,7 @@ sis900_open(struct net_device *net_dev)
        sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
 
        /* Enable all known interrupts by setting the interrupt mask. */
-       sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE);
+       sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE | TxDESC);
        sw32(cr, RxENA | sr32(cr));
        sw32(ier, IE);
 
@@ -1578,7 +1578,7 @@ static void sis900_tx_timeout(struct net_device *net_dev)
        sw32(txdp, sis_priv->tx_ring_dma);
 
        /* Enable all known interrupts by setting the interrupt mask. */
-       sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE);
+       sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE | TxDESC);
 }
 
 /**
@@ -1618,7 +1618,7 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
                        spin_unlock_irqrestore(&sis_priv->lock, flags);
                        return NETDEV_TX_OK;
        }
-       sis_priv->tx_ring[entry].cmdsts = (OWN | skb->len);
+       sis_priv->tx_ring[entry].cmdsts = (OWN | INTR | skb->len);
        sw32(cr, TxENA | sr32(cr));
 
        sis_priv->cur_tx ++;
@@ -1674,7 +1674,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance)
        do {
                status = sr32(isr);
 
-               if ((status & (HIBERR|TxURN|TxERR|TxIDLE|RxORN|RxERR|RxOK)) == 0)
+               if ((status & (HIBERR|TxURN|TxERR|TxIDLE|TxDESC|RxORN|RxERR|RxOK)) == 0)
                        /* nothing intresting happened */
                        break;
                handled = 1;
@@ -1684,7 +1684,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance)
                        /* Rx interrupt */
                        sis900_rx(net_dev);
 
-               if (status & (TxURN | TxERR | TxIDLE))
+               if (status & (TxURN | TxERR | TxIDLE | TxDESC))
                        /* Tx interrupt */
                        sis900_finish_xmit(net_dev);
 
@@ -1896,8 +1896,8 @@ static void sis900_finish_xmit (struct net_device *net_dev)
 
                if (tx_status & OWN) {
                        /* The packet is not transmitted yet (owned by hardware) !
-                        * Note: the interrupt is generated only when Tx Machine
-                        * is idle, so this is an almost impossible case */
+                        * Note: this is an almost impossible condition
+                        * in case of TxDESC ('descriptor interrupt') */
                        break;
                }
 
@@ -2473,7 +2473,7 @@ static int sis900_resume(struct pci_dev *pci_dev)
        sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
 
        /* Enable all known interrupts by setting the interrupt mask. */
-       sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE);
+       sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE | TxDESC);
        sw32(cr, RxENA | sr32(cr));
        sw32(ier, IE);