Skip to content

Commit 2b7b431

Browse files
Francois Romieudavem330
authored andcommitted
r8169: TSO fixes.
- the MSS value is actually contained in a 11 bits wide (0x7ff) field. The extra bit in the former MSSMask did encompass the TSO command bit ("LargeSend") as well (0xfff). Oops. - the Tx descriptor layout is not the same through the whole chipset family. The 8169 documentation, the 8168c documentation and Realtek's drivers (8.020.00, 1.019.00, 6.014.00) highlight two layouts: 1. 8169, 8168 up to 8168b (included) and 8101 2. {8102e, 8168c} and beyond - notwithstanding the "first descriptor" and "last descriptor" bits, the same Tx descriptor content is enforced when a packet consists of several descriptors. The chipsets are documented to require it. Credits go to David Dillow <dave@thedillows.org> for the original patch. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> Cc: Realtek <nic_swsd@realtek.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 47c2cdf commit 2b7b431

File tree

1 file changed

+137
-72
lines changed

1 file changed

+137
-72
lines changed

drivers/net/r8169.c

Lines changed: 137 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -134,47 +134,52 @@ enum mac_version {
134134
RTL_GIGA_MAC_VER_33 = 0x21, // 8168E
135135
};
136136

137-
#define _R(NAME,MAC,MASK) \
138-
{ .name = NAME, .mac_version = MAC, .RxConfigMask = MASK }
137+
enum rtl_tx_desc_version {
138+
RTL_TD_0 = 0,
139+
RTL_TD_1 = 1,
140+
};
141+
142+
#define _R(NAME,MAC,TD) \
143+
{ .name = NAME, .mac_version = MAC, .txd_version = TD }
139144

140145
static const struct {
141146
const char *name;
142147
u8 mac_version;
143-
u32 RxConfigMask; /* Clears the bits supported by this chip */
148+
enum rtl_tx_desc_version txd_version;
144149
} rtl_chip_info[] = {
145-
_R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169
146-
_R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S
147-
_R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S
148-
_R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB
149-
_R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd
150-
_R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe
151-
_R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E
152-
_R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E
153-
_R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E
154-
_R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E
155-
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E
156-
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E
157-
_R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139
158-
_R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139
159-
_R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139
160-
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E
161-
_R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E
162-
_R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E
163-
_R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E
164-
_R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E
165-
_R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E
166-
_R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E
167-
_R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E
168-
_R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E
169-
_R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E
170-
_R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E
171-
_R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, 0xff7e1880), // PCI-E
172-
_R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_28, 0xff7e1880), // PCI-E
173-
_R("RTL8105e", RTL_GIGA_MAC_VER_29, 0xff7e1880), // PCI-E
174-
_R("RTL8105e", RTL_GIGA_MAC_VER_30, 0xff7e1880), // PCI-E
175-
_R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_31, 0xff7e1880), // PCI-E
176-
_R("RTL8168e/8111e", RTL_GIGA_MAC_VER_32, 0xff7e1880), // PCI-E
177-
_R("RTL8168e/8111e", RTL_GIGA_MAC_VER_33, 0xff7e1880) // PCI-E
150+
_R("RTL8169", RTL_GIGA_MAC_VER_01, RTL_TD_0), // 8169
151+
_R("RTL8169s", RTL_GIGA_MAC_VER_02, RTL_TD_0), // 8169S
152+
_R("RTL8110s", RTL_GIGA_MAC_VER_03, RTL_TD_0), // 8110S
153+
_R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, RTL_TD_0), // 8169SB
154+
_R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, RTL_TD_0), // 8110SCd
155+
_R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, RTL_TD_0), // 8110SCe
156+
_R("RTL8102e", RTL_GIGA_MAC_VER_07, RTL_TD_1), // PCI-E
157+
_R("RTL8102e", RTL_GIGA_MAC_VER_08, RTL_TD_1), // PCI-E
158+
_R("RTL8102e", RTL_GIGA_MAC_VER_09, RTL_TD_1), // PCI-E
159+
_R("RTL8101e", RTL_GIGA_MAC_VER_10, RTL_TD_0), // PCI-E
160+
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, RTL_TD_0), // PCI-E
161+
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, RTL_TD_0), // PCI-E
162+
_R("RTL8101e", RTL_GIGA_MAC_VER_13, RTL_TD_0), // PCI-E 8139
163+
_R("RTL8100e", RTL_GIGA_MAC_VER_14, RTL_TD_0), // PCI-E 8139
164+
_R("RTL8100e", RTL_GIGA_MAC_VER_15, RTL_TD_0), // PCI-E 8139
165+
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, RTL_TD_0), // PCI-E
166+
_R("RTL8101e", RTL_GIGA_MAC_VER_16, RTL_TD_0), // PCI-E
167+
_R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, RTL_TD_1), // PCI-E
168+
_R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, RTL_TD_1), // PCI-E
169+
_R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, RTL_TD_1), // PCI-E
170+
_R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, RTL_TD_1), // PCI-E
171+
_R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, RTL_TD_1), // PCI-E
172+
_R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, RTL_TD_1), // PCI-E
173+
_R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, RTL_TD_1), // PCI-E
174+
_R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, RTL_TD_1), // PCI-E
175+
_R("RTL8168d/8111d", RTL_GIGA_MAC_VER_26, RTL_TD_1), // PCI-E
176+
_R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_27, RTL_TD_1), // PCI-E
177+
_R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_28, RTL_TD_1), // PCI-E
178+
_R("RTL8105e", RTL_GIGA_MAC_VER_29, RTL_TD_1), // PCI-E
179+
_R("RTL8105e", RTL_GIGA_MAC_VER_30, RTL_TD_1), // PCI-E
180+
_R("RTL8168dp/8111dp", RTL_GIGA_MAC_VER_31, RTL_TD_1), // PCI-E
181+
_R("RTL8168e/8111e", RTL_GIGA_MAC_VER_32, RTL_TD_1), // PCI-E
182+
_R("RTL8168e/8111e", RTL_GIGA_MAC_VER_33, RTL_TD_1) // PCI-E
178183
};
179184
#undef _R
180185

@@ -230,6 +235,9 @@ enum rtl_registers {
230235
IntrStatus = 0x3e,
231236
TxConfig = 0x40,
232237
RxConfig = 0x44,
238+
239+
#define RTL_RX_CONFIG_MASK 0xff7e1880u
240+
233241
RxMissed = 0x4c,
234242
Cfg9346 = 0x50,
235243
Config0 = 0x51,
@@ -452,21 +460,69 @@ enum rtl_register_content {
452460
CounterDump = 0x8,
453461
};
454462

455-
enum desc_status_bit {
463+
enum rtl_desc_bit {
464+
/* First doubleword. */
456465
DescOwn = (1 << 31), /* Descriptor is owned by NIC */
457466
RingEnd = (1 << 30), /* End of descriptor ring */
458467
FirstFrag = (1 << 29), /* First segment of a packet */
459468
LastFrag = (1 << 28), /* Final segment of a packet */
469+
};
470+
471+
/* Generic case. */
472+
enum rtl_tx_desc_bit {
473+
/* First doubleword. */
474+
TD_LSO = (1 << 27), /* Large Send Offload */
475+
#define TD_MSS_MAX 0x07ffu /* MSS value */
460476

461-
/* Tx private */
462-
LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */
463-
MSSShift = 16, /* MSS value position */
464-
MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */
465-
IPCS = (1 << 18), /* Calculate IP checksum */
466-
UDPCS = (1 << 17), /* Calculate UDP/IP checksum */
467-
TCPCS = (1 << 16), /* Calculate TCP/IP checksum */
468-
TxVlanTag = (1 << 17), /* Add VLAN tag */
477+
/* Second doubleword. */
478+
TxVlanTag = (1 << 17), /* Add VLAN tag */
479+
};
480+
481+
/* 8169, 8168b and 810x except 8102e. */
482+
enum rtl_tx_desc_bit_0 {
483+
/* First doubleword. */
484+
#define TD0_MSS_SHIFT 16 /* MSS position (11 bits) */
485+
TD0_TCP_CS = (1 << 16), /* Calculate TCP/IP checksum */
486+
TD0_UDP_CS = (1 << 17), /* Calculate UDP/IP checksum */
487+
TD0_IP_CS = (1 << 18), /* Calculate IP checksum */
488+
};
489+
490+
/* 8102e, 8168c and beyond. */
491+
enum rtl_tx_desc_bit_1 {
492+
/* Second doubleword. */
493+
#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */
494+
TD1_IP_CS = (1 << 29), /* Calculate IP checksum */
495+
TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */
496+
TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */
497+
};
469498

499+
static const struct rtl_tx_desc_info {
500+
struct {
501+
u32 udp;
502+
u32 tcp;
503+
} checksum;
504+
u16 mss_shift;
505+
u16 opts_offset;
506+
} tx_desc_info [] = {
507+
[RTL_TD_0] = {
508+
.checksum = {
509+
.udp = TD0_IP_CS | TD0_UDP_CS,
510+
.tcp = TD0_IP_CS | TD0_TCP_CS
511+
},
512+
.mss_shift = TD0_MSS_SHIFT,
513+
.opts_offset = 0
514+
},
515+
[RTL_TD_1] = {
516+
.checksum = {
517+
.udp = TD1_IP_CS | TD1_UDP_CS,
518+
.tcp = TD1_IP_CS | TD1_TCP_CS
519+
},
520+
.mss_shift = TD1_MSS_SHIFT,
521+
.opts_offset = 1
522+
}
523+
};
524+
525+
enum rtl_rx_desc_bit {
470526
/* Rx private */
471527
PID1 = (1 << 18), /* Protocol ID bit 1/2 */
472528
PID0 = (1 << 17), /* Protocol ID bit 2/2 */
@@ -531,8 +587,8 @@ struct rtl8169_private {
531587
struct napi_struct napi;
532588
spinlock_t lock; /* spin lock flag */
533589
u32 msg_enable;
534-
int chipset;
535-
int mac_version;
590+
u16 txd_version;
591+
u16 mac_version;
536592
u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
537593
u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
538594
u32 dirty_rx;
@@ -1288,7 +1344,7 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
12881344

12891345
static u32 rtl8169_fix_features(struct net_device *dev, u32 features)
12901346
{
1291-
if (dev->mtu > MSSMask)
1347+
if (dev->mtu > TD_MSS_MAX)
12921348
features &= ~NETIF_F_ALL_TSO;
12931349

12941350
return features;
@@ -3194,7 +3250,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
31943250
struct mii_if_info *mii;
31953251
struct net_device *dev;
31963252
void __iomem *ioaddr;
3197-
unsigned int i;
3253+
int chipset, i;
31983254
int rc;
31993255

32003256
if (netif_msg_drv(&debug)) {
@@ -3336,7 +3392,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
33363392
"driver bug, MAC version not found in rtl_chip_info\n");
33373393
goto err_out_msi_4;
33383394
}
3339-
tp->chipset = i;
3395+
chipset = i;
3396+
tp->txd_version = rtl_chip_info[chipset].txd_version;
33403397

33413398
RTL_W8(Cfg9346, Cfg9346_Unlock);
33423399
RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
@@ -3413,8 +3470,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
34133470
pci_set_drvdata(pdev, dev);
34143471

34153472
netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n",
3416-
rtl_chip_info[tp->chipset].name,
3417-
dev->base_addr, dev->dev_addr,
3473+
rtl_chip_info[chipset].name, dev->base_addr, dev->dev_addr,
34183474
(u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq);
34193475

34203476
if ((tp->mac_version == RTL_GIGA_MAC_VER_27) ||
@@ -3572,7 +3628,7 @@ static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
35723628
void __iomem *ioaddr = tp->mmio_addr;
35733629
u32 cfg = rtl8169_rx_config;
35743630

3575-
cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
3631+
cfg |= (RTL_R32(RxConfig) & RTL_RX_CONFIG_MASK);
35763632
RTL_W32(RxConfig, cfg);
35773633

35783634
/* Set DMA burst size and Interframe Gap Time */
@@ -4564,7 +4620,7 @@ static void rtl8169_tx_timeout(struct net_device *dev)
45644620
}
45654621

45664622
static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
4567-
u32 opts1)
4623+
u32 *opts)
45684624
{
45694625
struct skb_shared_info *info = skb_shinfo(skb);
45704626
unsigned int cur_frag, entry;
@@ -4592,9 +4648,11 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
45924648
}
45934649

45944650
/* anti gcc 2.95.3 bugware (sic) */
4595-
status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
4651+
status = opts[0] | len |
4652+
(RingEnd * !((entry + 1) % NUM_TX_DESC));
45964653

45974654
txd->opts1 = cpu_to_le32(status);
4655+
txd->opts2 = cpu_to_le32(opts[1]);
45984656
txd->addr = cpu_to_le64(mapping);
45994657

46004658
tp->tx_skb[entry].len = len;
@@ -4612,23 +4670,26 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
46124670
return -EIO;
46134671
}
46144672

4615-
static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev)
4673+
static inline void rtl8169_tso_csum(struct rtl8169_private *tp,
4674+
struct sk_buff *skb, u32 *opts)
46164675
{
4676+
const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
46174677
u32 mss = skb_shinfo(skb)->gso_size;
4678+
int offset = info->opts_offset;
46184679

4619-
if (mss)
4620-
return LargeSend | ((mss & MSSMask) << MSSShift);
4621-
4622-
if (skb->ip_summed == CHECKSUM_PARTIAL) {
4680+
if (mss) {
4681+
opts[0] |= TD_LSO;
4682+
opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift;
4683+
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
46234684
const struct iphdr *ip = ip_hdr(skb);
46244685

46254686
if (ip->protocol == IPPROTO_TCP)
4626-
return IPCS | TCPCS;
4687+
opts[offset] |= info->checksum.tcp;
46274688
else if (ip->protocol == IPPROTO_UDP)
4628-
return IPCS | UDPCS;
4629-
WARN_ON(1); /* we need a WARN() */
4689+
opts[offset] |= info->checksum.udp;
4690+
else
4691+
WARN_ON_ONCE(1);
46304692
}
4631-
return 0;
46324693
}
46334694

46344695
static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
@@ -4641,7 +4702,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
46414702
struct device *d = &tp->pci_dev->dev;
46424703
dma_addr_t mapping;
46434704
u32 status, len;
4644-
u32 opts1;
4705+
u32 opts[2];
46454706
int frags;
46464707

46474708
if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) {
@@ -4662,24 +4723,28 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
46624723

46634724
tp->tx_skb[entry].len = len;
46644725
txd->addr = cpu_to_le64(mapping);
4665-
txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb));
46664726

4667-
opts1 = DescOwn | rtl8169_tso_csum(skb, dev);
4727+
opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb));
4728+
opts[0] = DescOwn;
46684729

4669-
frags = rtl8169_xmit_frags(tp, skb, opts1);
4730+
rtl8169_tso_csum(tp, skb, opts);
4731+
4732+
frags = rtl8169_xmit_frags(tp, skb, opts);
46704733
if (frags < 0)
46714734
goto err_dma_1;
46724735
else if (frags)
4673-
opts1 |= FirstFrag;
4736+
opts[0] |= FirstFrag;
46744737
else {
4675-
opts1 |= FirstFrag | LastFrag;
4738+
opts[0] |= FirstFrag | LastFrag;
46764739
tp->tx_skb[entry].skb = skb;
46774740
}
46784741

4742+
txd->opts2 = cpu_to_le32(opts[1]);
4743+
46794744
wmb();
46804745

46814746
/* anti gcc 2.95.3 bugware (sic) */
4682-
status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
4747+
status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
46834748
txd->opts1 = cpu_to_le32(status);
46844749

46854750
tp->cur_tx += frags + 1;
@@ -5167,7 +5232,7 @@ static void rtl_set_rx_mode(struct net_device *dev)
51675232
spin_lock_irqsave(&tp->lock, flags);
51685233

51695234
tmp = rtl8169_rx_config | rx_mode |
5170-
(RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
5235+
(RTL_R32(RxConfig) & RTL_RX_CONFIG_MASK);
51715236

51725237
if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
51735238
u32 data = mc_filter[0];

0 commit comments

Comments
 (0)