* [PATCH,RFT] 8139cp TSO support
@ 2004-08-29 21:22 Jeff Garzik
2004-08-29 22:28 ` Francois Romieu
0 siblings, 1 reply; 8+ messages in thread
From: Jeff Garzik @ 2004-08-29 21:22 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, romieu
Just added TSO support to the 8139cp driver, as it looked fairly
straightforward.
Anyone willing to give this some testing?
Also, the r8169 implementation should be similar, if someone (Francois?)
wants to tackle it.
Jeff
# ChangeSet
# 2004/08/29 17:19:44-04:00 jgarzik@pobox.com
# [netdrvr 8139cp] TSO support
#
diff -Nru a/drivers/net/8139cp.c b/drivers/net/8139cp.c
--- a/drivers/net/8139cp.c 2004-08-29 17:19:59 -04:00
+++ b/drivers/net/8139cp.c 2004-08-29 17:19:59 -04:00
@@ -185,6 +185,9 @@
RingEnd = (1 << 30), /* End of descriptor ring */
FirstFrag = (1 << 29), /* First segment of a packet */
LastFrag = (1 << 28), /* Final segment of a packet */
+ LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */
+ MSSShift = 16, /* MSS value position */
+ MSSMask = 0xfff, /* MSS value: 11 bits */
TxError = (1 << 23), /* Tx error summary */
RxError = (1 << 20), /* Rx error summary */
IPCS = (1 << 18), /* Calculate IP checksum */
@@ -747,10 +750,11 @@
{
struct cp_private *cp = netdev_priv(dev);
unsigned entry;
- u32 eor;
+ u32 eor, flags;
#if CP_VLAN_TAG_USED
u32 vlan_tag = 0;
#endif
+ int mss = 0;
spin_lock_irq(&cp->lock);
@@ -770,6 +774,9 @@
entry = cp->tx_head;
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
+ if (dev->features & NETIF_F_TSO)
+ mss = skb_shinfo(skb)->tso_size;
+
if (skb_shinfo(skb)->nr_frags == 0) {
struct cp_desc *txd = &cp->tx_ring[entry];
u32 len;
@@ -781,21 +788,21 @@
txd->addr = cpu_to_le64(mapping);
wmb();
- if (skb->ip_summed == CHECKSUM_HW) {
+ flags = eor | len | DescOwn | FirstFrag | LastFrag;
+
+ if (mss)
+ flags |= LargeSend | ((mss & MSSMask) << MSSShift);
+ else if (skb->ip_summed == CHECKSUM_HW) {
const struct iphdr *ip = skb->nh.iph;
if (ip->protocol == IPPROTO_TCP)
- txd->opts1 = cpu_to_le32(eor | len | DescOwn |
- FirstFrag | LastFrag |
- IPCS | TCPCS);
+ flags |= IPCS | TCPCS;
else if (ip->protocol == IPPROTO_UDP)
- txd->opts1 = cpu_to_le32(eor | len | DescOwn |
- FirstFrag | LastFrag |
- IPCS | UDPCS);
+ flags |= IPCS | UDPCS;
else
BUG();
- } else
- txd->opts1 = cpu_to_le32(eor | len | DescOwn |
- FirstFrag | LastFrag);
+ }
+
+ txd->opts1 = cpu_to_le32(flags);
wmb();
cp->tx_skb[entry].skb = skb;
@@ -834,16 +841,19 @@
len, PCI_DMA_TODEVICE);
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
- if (skb->ip_summed == CHECKSUM_HW) {
- ctrl = eor | len | DescOwn | IPCS;
+ ctrl = eor | len | DescOwn;
+
+ if (mss)
+ ctrl |= LargeSend |
+ ((mss & MSSMask) << MSSShift);
+ else if (skb->ip_summed == CHECKSUM_HW) {
if (ip->protocol == IPPROTO_TCP)
- ctrl |= TCPCS;
+ ctrl |= IPCS | TCPCS;
else if (ip->protocol == IPPROTO_UDP)
- ctrl |= UDPCS;
+ ctrl |= IPCS | UDPCS;
else
BUG();
- } else
- ctrl = eor | len | DescOwn;
+ }
if (frag == skb_shinfo(skb)->nr_frags - 1)
ctrl |= LastFrag;
@@ -1536,6 +1546,8 @@
.set_tx_csum = ethtool_op_set_tx_csum, /* local! */
.get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = ethtool_op_set_tso,
.get_regs = cp_get_regs,
.get_wol = cp_get_wol,
.set_wol = cp_set_wol,
@@ -1765,6 +1777,10 @@
if (pci_using_dac)
dev->features |= NETIF_F_HIGHDMA;
+
+#if 0 /* disabled by default until verified */
+ dev->features |= NETIF_F_TSO;
+#endif
dev->irq = pdev->irq;
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH,RFT] 8139cp TSO support
2004-08-29 21:22 [PATCH,RFT] 8139cp TSO support Jeff Garzik
@ 2004-08-29 22:28 ` Francois Romieu
2004-08-29 23:02 ` Jeff Garzik
0 siblings, 1 reply; 8+ messages in thread
From: Francois Romieu @ 2004-08-29 22:28 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, jgarzik
Jeff Garzik <jgarzik@pobox.com> :
[...]
> Also, the r8169 implementation should be similar, if someone (Francois?)
> wants to tackle it.
I'll copy and test it tomorrow on r8169 if nobody beats me.
On a related note, 8139cp probably wants something like the patch below for
the usual SG handling (on top of 2.6.9-rc1 + -mm1 + TSO patch):
- suspicious length in pci_unmap_single;
- wait for the last frag before freeing the relevant skb;
- no need to crash when facing some unexpected csum combination.
diff -puN drivers/net/8139cp.c~8139cp-010 drivers/net/8139cp.c
--- linux-2.6.9-rc1/drivers/net/8139cp.c~8139cp-010 2004-08-29 23:47:07.000000000 +0200
+++ linux-2.6.9-rc1-fr/drivers/net/8139cp.c 2004-08-30 00:16:13.000000000 +0200
@@ -314,7 +314,7 @@ struct cp_desc {
struct ring_info {
struct sk_buff *skb;
dma_addr_t mapping;
- unsigned frag;
+ u32 len;
};
struct cp_dma_stats {
@@ -708,7 +708,7 @@ static void cp_tx (struct cp_private *cp
BUG();
pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
- skb->len, PCI_DMA_TODEVICE);
+ cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
if (status & LastFrag) {
if (status & (TxError | TxFIFOUnder)) {
@@ -799,7 +799,7 @@ static int cp_start_xmit (struct sk_buff
else if (ip->protocol == IPPROTO_UDP)
flags |= IPCS | UDPCS;
else
- BUG();
+ WARN_ON(1); /* we need a WARN() */
}
txd->opts1 = cpu_to_le32(flags);
@@ -807,7 +807,6 @@ static int cp_start_xmit (struct sk_buff
cp->tx_skb[entry].skb = skb;
cp->tx_skb[entry].mapping = mapping;
- cp->tx_skb[entry].frag = 0;
entry = NEXT_TX(entry);
} else {
struct cp_desc *txd;
@@ -824,8 +823,8 @@ static int cp_start_xmit (struct sk_buff
first_mapping = pci_map_single(cp->pdev, skb->data,
first_len, PCI_DMA_TODEVICE);
cp->tx_skb[entry].skb = skb;
+ cp->tx_skb[entry].len = first_len;
cp->tx_skb[entry].mapping = first_mapping;
- cp->tx_skb[entry].frag = 1;
entry = NEXT_TX(entry);
for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
@@ -868,7 +867,7 @@ static int cp_start_xmit (struct sk_buff
cp->tx_skb[entry].skb = skb;
cp->tx_skb[entry].mapping = mapping;
- cp->tx_skb[entry].frag = frag + 2;
+ cp->tx_skb[entry].len = len;
entry = NEXT_TX(entry);
}
@@ -1082,7 +1081,6 @@ static int cp_refill_rx (struct cp_priva
cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
cp->rx_skb[i].skb = skb;
- cp->rx_skb[i].frag = 0;
cp->rx_ring[i].opts2 = 0;
cp->rx_ring[i].addr = cpu_to_le64(cp->rx_skb[i].mapping);
@@ -1134,9 +1132,6 @@ static void cp_clean_rings (struct cp_pr
{
unsigned i;
- memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
- memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
-
for (i = 0; i < CP_RX_RING_SIZE; i++) {
if (cp->rx_skb[i].skb) {
pci_unmap_single(cp->pdev, cp->rx_skb[i].mapping,
@@ -1148,13 +1143,18 @@ static void cp_clean_rings (struct cp_pr
for (i = 0; i < CP_TX_RING_SIZE; i++) {
if (cp->tx_skb[i].skb) {
struct sk_buff *skb = cp->tx_skb[i].skb;
+
pci_unmap_single(cp->pdev, cp->tx_skb[i].mapping,
- skb->len, PCI_DMA_TODEVICE);
- dev_kfree_skb(skb);
+ cp->tx_skb[i].len, PCI_DMA_TODEVICE);
+ if (le32_to_cpu(cp->tx_ring[i].opts1) & LastFrag)
+ dev_kfree_skb(skb);
cp->net_stats.tx_dropped++;
}
}
+ memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
+ memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
+
memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE);
memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE);
}
_
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH,RFT] 8139cp TSO support
2004-08-29 22:28 ` Francois Romieu
@ 2004-08-29 23:02 ` Jeff Garzik
2004-08-30 21:52 ` Francois Romieu
0 siblings, 1 reply; 8+ messages in thread
From: Jeff Garzik @ 2004-08-29 23:02 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, linux-kernel
Francois Romieu wrote:
> Jeff Garzik <jgarzik@pobox.com> :
> [...]
>
>>Also, the r8169 implementation should be similar, if someone (Francois?)
>>wants to tackle it.
>
>
> I'll copy and test it tomorrow on r8169 if nobody beats me.
>
> On a related note, 8139cp probably wants something like the patch below for
> the usual SG handling (on top of 2.6.9-rc1 + -mm1 + TSO patch):
>
> - suspicious length in pci_unmap_single;
> - wait for the last frag before freeing the relevant skb;
> - no need to crash when facing some unexpected csum combination.
Looks OK except for
> diff -puN drivers/net/8139cp.c~8139cp-010 drivers/net/8139cp.c
> --- linux-2.6.9-rc1/drivers/net/8139cp.c~8139cp-010 2004-08-29 23:47:07.000000000 +0200
> +++ linux-2.6.9-rc1-fr/drivers/net/8139cp.c 2004-08-30 00:16:13.000000000 +0200
> @@ -807,7 +807,6 @@ static int cp_start_xmit (struct sk_buff
>
> cp->tx_skb[entry].skb = skb;
> cp->tx_skb[entry].mapping = mapping;
> - cp->tx_skb[entry].frag = 0;
> entry = NEXT_TX(entry);
> } else {
> struct cp_desc *txd;
You definitely want to set .len on the no-frags path...
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH,RFT] 8139cp TSO support
2004-08-29 23:02 ` Jeff Garzik
@ 2004-08-30 21:52 ` Francois Romieu
2004-08-30 21:56 ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Francois Romieu
0 siblings, 1 reply; 8+ messages in thread
From: Francois Romieu @ 2004-08-30 21:52 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev, linux-kernel
Jeff Garzik <jgarzik@pobox.com> :
[...]
> You definitely want to set .len on the no-frags path...
Oops.. Patch follows.
I won't have a neat tso enabled r8169 driver today. Something goes wrong.
--
Ueimor
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes
2004-08-30 21:52 ` Francois Romieu
@ 2004-08-30 21:56 ` Francois Romieu
2004-08-30 21:58 ` [PATCH 2.6.9-rc1-mm1-tso 2/2] 8139cp: DAC support fix Francois Romieu
2004-08-31 7:20 ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Jeff Garzik
0 siblings, 2 replies; 8+ messages in thread
From: Francois Romieu @ 2004-08-30 21:56 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev, linux-kernel
- suspicious length in pci_unmap_single;
- wait for the last frag before freeing the relevant skb;
- no need to crash when facing some unexpected csum combination.
diff -puN drivers/net/8139cp.c~8139cp-010 drivers/net/8139cp.c
--- linux-2.6.9-rc1/drivers/net/8139cp.c~8139cp-010 2004-08-29 23:47:07.000000000 +0200
+++ linux-2.6.9-rc1-fr/drivers/net/8139cp.c 2004-08-30 21:21:23.000000000 +0200
@@ -314,7 +314,7 @@ struct cp_desc {
struct ring_info {
struct sk_buff *skb;
dma_addr_t mapping;
- unsigned frag;
+ u32 len;
};
struct cp_dma_stats {
@@ -708,7 +708,7 @@ static void cp_tx (struct cp_private *cp
BUG();
pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
- skb->len, PCI_DMA_TODEVICE);
+ cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
if (status & LastFrag) {
if (status & (TxError | TxFIFOUnder)) {
@@ -799,7 +799,7 @@ static int cp_start_xmit (struct sk_buff
else if (ip->protocol == IPPROTO_UDP)
flags |= IPCS | UDPCS;
else
- BUG();
+ WARN_ON(1); /* we need a WARN() */
}
txd->opts1 = cpu_to_le32(flags);
@@ -807,7 +807,7 @@ static int cp_start_xmit (struct sk_buff
cp->tx_skb[entry].skb = skb;
cp->tx_skb[entry].mapping = mapping;
- cp->tx_skb[entry].frag = 0;
+ cp->tx_skb[entry].len = len;
entry = NEXT_TX(entry);
} else {
struct cp_desc *txd;
@@ -825,7 +825,7 @@ static int cp_start_xmit (struct sk_buff
first_len, PCI_DMA_TODEVICE);
cp->tx_skb[entry].skb = skb;
cp->tx_skb[entry].mapping = first_mapping;
- cp->tx_skb[entry].frag = 1;
+ cp->tx_skb[entry].len = first_len;
entry = NEXT_TX(entry);
for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
@@ -868,7 +868,7 @@ static int cp_start_xmit (struct sk_buff
cp->tx_skb[entry].skb = skb;
cp->tx_skb[entry].mapping = mapping;
- cp->tx_skb[entry].frag = frag + 2;
+ cp->tx_skb[entry].len = len;
entry = NEXT_TX(entry);
}
@@ -1082,7 +1082,6 @@ static int cp_refill_rx (struct cp_priva
cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
cp->rx_skb[i].skb = skb;
- cp->rx_skb[i].frag = 0;
cp->rx_ring[i].opts2 = 0;
cp->rx_ring[i].addr = cpu_to_le64(cp->rx_skb[i].mapping);
@@ -1134,9 +1133,6 @@ static void cp_clean_rings (struct cp_pr
{
unsigned i;
- memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
- memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
-
for (i = 0; i < CP_RX_RING_SIZE; i++) {
if (cp->rx_skb[i].skb) {
pci_unmap_single(cp->pdev, cp->rx_skb[i].mapping,
@@ -1148,13 +1144,18 @@ static void cp_clean_rings (struct cp_pr
for (i = 0; i < CP_TX_RING_SIZE; i++) {
if (cp->tx_skb[i].skb) {
struct sk_buff *skb = cp->tx_skb[i].skb;
+
pci_unmap_single(cp->pdev, cp->tx_skb[i].mapping,
- skb->len, PCI_DMA_TODEVICE);
- dev_kfree_skb(skb);
+ cp->tx_skb[i].len, PCI_DMA_TODEVICE);
+ if (le32_to_cpu(cp->tx_ring[i].opts1) & LastFrag)
+ dev_kfree_skb(skb);
cp->net_stats.tx_dropped++;
}
}
+ memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
+ memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
+
memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE);
memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE);
}
_
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2.6.9-rc1-mm1-tso 2/2] 8139cp: DAC support fix
2004-08-30 21:56 ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Francois Romieu
@ 2004-08-30 21:58 ` Francois Romieu
2004-08-31 7:19 ` Jeff Garzik
2004-08-31 7:20 ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Jeff Garzik
1 sibling, 1 reply; 8+ messages in thread
From: Francois Romieu @ 2004-08-30 21:58 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev, linux-kernel
Wrong unit for sizeof().
diff -puN drivers/net/8139cp.c~8139cp-020 drivers/net/8139cp.c
--- linux-2.6.9-rc1/drivers/net/8139cp.c~8139cp-020 2004-08-30 23:34:16.000000000 +0200
+++ linux-2.6.9-rc1-fr/drivers/net/8139cp.c 2004-08-30 23:35:09.000000000 +0200
@@ -1711,7 +1711,7 @@ static int cp_init_one (struct pci_dev *
}
/* Configure DMA attributes. */
- if ((sizeof(dma_addr_t) > 32) &&
+ if ((sizeof(dma_addr_t) > 4) &&
!pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL) &&
!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
pci_using_dac = 1;
_
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2.6.9-rc1-mm1-tso 2/2] 8139cp: DAC support fix
2004-08-30 21:58 ` [PATCH 2.6.9-rc1-mm1-tso 2/2] 8139cp: DAC support fix Francois Romieu
@ 2004-08-31 7:19 ` Jeff Garzik
0 siblings, 0 replies; 8+ messages in thread
From: Jeff Garzik @ 2004-08-31 7:19 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, linux-kernel
applied
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes
2004-08-30 21:56 ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Francois Romieu
2004-08-30 21:58 ` [PATCH 2.6.9-rc1-mm1-tso 2/2] 8139cp: DAC support fix Francois Romieu
@ 2004-08-31 7:20 ` Jeff Garzik
1 sibling, 0 replies; 8+ messages in thread
From: Jeff Garzik @ 2004-08-31 7:20 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, linux-kernel
applied
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2004-08-31 7:20 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-29 21:22 [PATCH,RFT] 8139cp TSO support Jeff Garzik
2004-08-29 22:28 ` Francois Romieu
2004-08-29 23:02 ` Jeff Garzik
2004-08-30 21:52 ` Francois Romieu
2004-08-30 21:56 ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Francois Romieu
2004-08-30 21:58 ` [PATCH 2.6.9-rc1-mm1-tso 2/2] 8139cp: DAC support fix Francois Romieu
2004-08-31 7:19 ` Jeff Garzik
2004-08-31 7:20 ` [PATCH 2.6.9-rc1-mm1-tso 1/2] 8139cp: SG support fixes Jeff Garzik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).