Skip to content

Commit 8b7a704

Browse files
dwmw2davem330
authored andcommitted
8139cp: Fix GSO MSS handling
When fixing the TSO support I noticed we just mask ->gso_size with the MSSMask value and don't care about the consequences. Provide a .ndo_features_check() method which drops the NETIF_F_TSO feature for any skb which would exceed the maximum, and thus forces it to be segmented by software. Then we can stop the masking in cp_start_xmit(), and just WARN if the maximum is exceeded, which should now never happen. Finally, Francois Romieu noticed that we didn't even have the right value for MSSMask anyway; it should be 0x7ff (11 bits) not 0xfff. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 5a58f22 commit 8b7a704

File tree

1 file changed

+18
-2
lines changed

1 file changed

+18
-2
lines changed

drivers/net/ethernet/realtek/8139cp.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ enum {
175175
LastFrag = (1 << 28), /* Final segment of a packet */
176176
LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */
177177
MSSShift = 16, /* MSS value position */
178-
MSSMask = 0xfff, /* MSS value: 11 bits */
178+
MSSMask = 0x7ff, /* MSS value: 11 bits */
179179
TxError = (1 << 23), /* Tx error summary */
180180
RxError = (1 << 20), /* Rx error summary */
181181
IPCS = (1 << 18), /* Calculate IP checksum */
@@ -754,10 +754,16 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
754754
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
755755
mss = skb_shinfo(skb)->gso_size;
756756

757+
if (mss > MSSMask) {
758+
WARN_ONCE(1, "Net bug: GSO size %d too large for 8139CP\n",
759+
mss);
760+
goto out_dma_error;
761+
}
762+
757763
opts2 = cpu_to_le32(cp_tx_vlan_tag(skb));
758764
opts1 = DescOwn;
759765
if (mss)
760-
opts1 |= LargeSend | ((mss & MSSMask) << MSSShift);
766+
opts1 |= LargeSend | (mss << MSSShift);
761767
else if (skb->ip_summed == CHECKSUM_PARTIAL) {
762768
const struct iphdr *ip = ip_hdr(skb);
763769
if (ip->protocol == IPPROTO_TCP)
@@ -1852,6 +1858,15 @@ static void cp_set_d3_state (struct cp_private *cp)
18521858
pci_set_power_state (cp->pdev, PCI_D3hot);
18531859
}
18541860

1861+
static netdev_features_t cp_features_check(struct sk_buff *skb,
1862+
struct net_device *dev,
1863+
netdev_features_t features)
1864+
{
1865+
if (skb_shinfo(skb)->gso_size > MSSMask)
1866+
features &= ~NETIF_F_TSO;
1867+
1868+
return vlan_features_check(skb, features);
1869+
}
18551870
static const struct net_device_ops cp_netdev_ops = {
18561871
.ndo_open = cp_open,
18571872
.ndo_stop = cp_close,
@@ -1864,6 +1879,7 @@ static const struct net_device_ops cp_netdev_ops = {
18641879
.ndo_tx_timeout = cp_tx_timeout,
18651880
.ndo_set_features = cp_set_features,
18661881
.ndo_change_mtu = cp_change_mtu,
1882+
.ndo_features_check = cp_features_check,
18671883

18681884
#ifdef CONFIG_NET_POLL_CONTROLLER
18691885
.ndo_poll_controller = cp_poll_controller,

0 commit comments

Comments
 (0)