aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/realtek
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2015-09-24 06:38:22 -0400
committerDavid S. Miller <davem@davemloft.net>2015-09-27 01:38:34 -0400
commit8b7a7048220f86547db31de0abe1ea6dd2cfa892 (patch)
treed2fc6cc721822b02e326569b2d011bd906a6842b /drivers/net/ethernet/realtek
parent5a58f227790faded5a3ef6075f3ddd65093e0f86 (diff)
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>
Diffstat (limited to 'drivers/net/ethernet/realtek')
-rw-r--r--drivers/net/ethernet/realtek/8139cp.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index e5173f33428b..deae10d7426d 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -175,7 +175,7 @@ enum {
175 LastFrag = (1 << 28), /* Final segment of a packet */ 175 LastFrag = (1 << 28), /* Final segment of a packet */
176 LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ 176 LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */
177 MSSShift = 16, /* MSS value position */ 177 MSSShift = 16, /* MSS value position */
178 MSSMask = 0xfff, /* MSS value: 11 bits */ 178 MSSMask = 0x7ff, /* MSS value: 11 bits */
179 TxError = (1 << 23), /* Tx error summary */ 179 TxError = (1 << 23), /* Tx error summary */
180 RxError = (1 << 20), /* Rx error summary */ 180 RxError = (1 << 20), /* Rx error summary */
181 IPCS = (1 << 18), /* Calculate IP checksum */ 181 IPCS = (1 << 18), /* Calculate IP checksum */
@@ -754,10 +754,16 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
754 eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; 754 eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
755 mss = skb_shinfo(skb)->gso_size; 755 mss = skb_shinfo(skb)->gso_size;
756 756
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
757 opts2 = cpu_to_le32(cp_tx_vlan_tag(skb)); 763 opts2 = cpu_to_le32(cp_tx_vlan_tag(skb));
758 opts1 = DescOwn; 764 opts1 = DescOwn;
759 if (mss) 765 if (mss)
760 opts1 |= LargeSend | ((mss & MSSMask) << MSSShift); 766 opts1 |= LargeSend | (mss << MSSShift);
761 else if (skb->ip_summed == CHECKSUM_PARTIAL) { 767 else if (skb->ip_summed == CHECKSUM_PARTIAL) {
762 const struct iphdr *ip = ip_hdr(skb); 768 const struct iphdr *ip = ip_hdr(skb);
763 if (ip->protocol == IPPROTO_TCP) 769 if (ip->protocol == IPPROTO_TCP)
@@ -1852,6 +1858,15 @@ static void cp_set_d3_state (struct cp_private *cp)
1852 pci_set_power_state (cp->pdev, PCI_D3hot); 1858 pci_set_power_state (cp->pdev, PCI_D3hot);
1853} 1859}
1854 1860
1861static 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}
1855static const struct net_device_ops cp_netdev_ops = { 1870static const struct net_device_ops cp_netdev_ops = {
1856 .ndo_open = cp_open, 1871 .ndo_open = cp_open,
1857 .ndo_stop = cp_close, 1872 .ndo_stop = cp_close,
@@ -1864,6 +1879,7 @@ static const struct net_device_ops cp_netdev_ops = {
1864 .ndo_tx_timeout = cp_tx_timeout, 1879 .ndo_tx_timeout = cp_tx_timeout,
1865 .ndo_set_features = cp_set_features, 1880 .ndo_set_features = cp_set_features,
1866 .ndo_change_mtu = cp_change_mtu, 1881 .ndo_change_mtu = cp_change_mtu,
1882 .ndo_features_check = cp_features_check,
1867 1883
1868#ifdef CONFIG_NET_POLL_CONTROLLER 1884#ifdef CONFIG_NET_POLL_CONTROLLER
1869 .ndo_poll_controller = cp_poll_controller, 1885 .ndo_poll_controller = cp_poll_controller,