Commit 8ac8a010 authored by Sergej Benilov's avatar Sergej Benilov Committed by David S. Miller

sis900: fix TX completion

Since commit 605ad7f1 "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: default avatarSergej Benilov <sergej.benilov@googlemail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d0bb82fd
...@@ -1057,7 +1057,7 @@ sis900_open(struct net_device *net_dev) ...@@ -1057,7 +1057,7 @@ sis900_open(struct net_device *net_dev)
sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED); sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
/* Enable all known interrupts by setting the interrupt mask. */ /* 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(cr, RxENA | sr32(cr));
sw32(ier, IE); sw32(ier, IE);
...@@ -1578,7 +1578,7 @@ static void sis900_tx_timeout(struct net_device *net_dev) ...@@ -1578,7 +1578,7 @@ static void sis900_tx_timeout(struct net_device *net_dev)
sw32(txdp, sis_priv->tx_ring_dma); sw32(txdp, sis_priv->tx_ring_dma);
/* Enable all known interrupts by setting the interrupt mask. */ /* 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) ...@@ -1618,7 +1618,7 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
spin_unlock_irqrestore(&sis_priv->lock, flags); spin_unlock_irqrestore(&sis_priv->lock, flags);
return NETDEV_TX_OK; 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)); sw32(cr, TxENA | sr32(cr));
sis_priv->cur_tx ++; sis_priv->cur_tx ++;
...@@ -1674,7 +1674,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance) ...@@ -1674,7 +1674,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance)
do { do {
status = sr32(isr); 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 */ /* nothing intresting happened */
break; break;
handled = 1; handled = 1;
...@@ -1684,7 +1684,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance) ...@@ -1684,7 +1684,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance)
/* Rx interrupt */ /* Rx interrupt */
sis900_rx(net_dev); sis900_rx(net_dev);
if (status & (TxURN | TxERR | TxIDLE)) if (status & (TxURN | TxERR | TxIDLE | TxDESC))
/* Tx interrupt */ /* Tx interrupt */
sis900_finish_xmit(net_dev); sis900_finish_xmit(net_dev);
...@@ -1896,8 +1896,8 @@ static void sis900_finish_xmit (struct net_device *net_dev) ...@@ -1896,8 +1896,8 @@ static void sis900_finish_xmit (struct net_device *net_dev)
if (tx_status & OWN) { if (tx_status & OWN) {
/* The packet is not transmitted yet (owned by hardware) ! /* The packet is not transmitted yet (owned by hardware) !
* Note: the interrupt is generated only when Tx Machine * Note: this is an almost impossible condition
* is idle, so this is an almost impossible case */ * in case of TxDESC ('descriptor interrupt') */
break; break;
} }
...@@ -2473,7 +2473,7 @@ static int sis900_resume(struct pci_dev *pci_dev) ...@@ -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); sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
/* Enable all known interrupts by setting the interrupt mask. */ /* 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(cr, RxENA | sr32(cr));
sw32(ier, IE); sw32(ier, IE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment