diff options
author | John Crispin <john@openwrt.org> | 2015-10-19 10:09:54 +0000 |
---|---|---|
committer | John Crispin <john@openwrt.org> | 2015-10-19 10:09:54 +0000 |
commit | 024083a556788895ee5f98c7acbd08b7ac2e278e (patch) | |
tree | 4cd35a99512c30620dd28c5a47a9c86c3f8260a2 /target/linux/generic/patches-4.1/761-8139cp-fixes-from-4.4.patch | |
parent | 1c74d046edd754c7aff41a0a7d60bf94f307b8b2 (diff) | |
download | mtk-20170518-024083a556788895ee5f98c7acbd08b7ac2e278e.zip mtk-20170518-024083a556788895ee5f98c7acbd08b7ac2e278e.tar.gz mtk-20170518-024083a556788895ee5f98c7acbd08b7ac2e278e.tar.bz2 |
generic: add 8139cp fixes, enable hardware csum/tso on 4.0+
This contains two sets of fixes for the 8139cp driver.
For all kernel versions older than 4.3, we can apply the fixes from the
4.3-rc4 kernel. In particular, these fix the TX timeout recovery which
is causing my Geos to lock up until the hardware watchdog kicks in.
For 4.0 and later kernels, we can also apply the additional improvements
which are going into 4.4 to fix and enable hardware checksum/TSO
offload. Backporting those to older kernels is non-trivial.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
SVN-Revision: 47220
Diffstat (limited to 'target/linux/generic/patches-4.1/761-8139cp-fixes-from-4.4.patch')
-rw-r--r-- | target/linux/generic/patches-4.1/761-8139cp-fixes-from-4.4.patch | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/target/linux/generic/patches-4.1/761-8139cp-fixes-from-4.4.patch b/target/linux/generic/patches-4.1/761-8139cp-fixes-from-4.4.patch new file mode 100644 index 0000000..cb605e5 --- /dev/null +++ b/target/linux/generic/patches-4.1/761-8139cp-fixes-from-4.4.patch @@ -0,0 +1,105 @@ +commit 8b7a7048220f86547db31de0abe1ea6dd2cfa892 +Author: David Woodhouse <dwmw2@infradead.org> +Date: Thu Sep 24 11:38:22 2015 +0100 + + 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> + +commit 5a58f227790faded5a3ef6075f3ddd65093e0f86 +Author: David Woodhouse <David.Woodhouse@intel.com> +Date: Wed Sep 23 09:46:09 2015 +0100 + + 8139cp: Enable offload features by default + + I fixed TSO. Hardware checksum and scatter/gather also appear to be + working correctly both on real hardware and in QEMU's emulation. + + Let's enable them by default and see if anyone screams... + + Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> + Signed-off-by: David S. Miller <davem@davemloft.net> +diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c +index 686334f..deae10d 100644 +--- a/drivers/net/ethernet/realtek/8139cp.c ++++ b/drivers/net/ethernet/realtek/8139cp.c +@@ -175,7 +175,7 @@ enum { + 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 */ ++ MSSMask = 0x7ff, /* MSS value: 11 bits */ + TxError = (1 << 23), /* Tx error summary */ + RxError = (1 << 20), /* Rx error summary */ + IPCS = (1 << 18), /* Calculate IP checksum */ +@@ -754,10 +754,16 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, + eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; + mss = skb_shinfo(skb)->gso_size; + ++ if (mss > MSSMask) { ++ WARN_ONCE(1, "Net bug: GSO size %d too large for 8139CP\n", ++ mss); ++ goto out_dma_error; ++ } ++ + opts2 = cpu_to_le32(cp_tx_vlan_tag(skb)); + opts1 = DescOwn; + if (mss) +- opts1 |= LargeSend | ((mss & MSSMask) << MSSShift); ++ opts1 |= LargeSend | (mss << MSSShift); + else if (skb->ip_summed == CHECKSUM_PARTIAL) { + const struct iphdr *ip = ip_hdr(skb); + if (ip->protocol == IPPROTO_TCP) +@@ -1852,6 +1858,15 @@ static void cp_set_d3_state (struct cp_private *cp) + pci_set_power_state (cp->pdev, PCI_D3hot); + } + ++static netdev_features_t cp_features_check(struct sk_buff *skb, ++ struct net_device *dev, ++ netdev_features_t features) ++{ ++ if (skb_shinfo(skb)->gso_size > MSSMask) ++ features &= ~NETIF_F_TSO; ++ ++ return vlan_features_check(skb, features); ++} + static const struct net_device_ops cp_netdev_ops = { + .ndo_open = cp_open, + .ndo_stop = cp_close, +@@ -1864,6 +1879,7 @@ static const struct net_device_ops cp_netdev_ops = { + .ndo_tx_timeout = cp_tx_timeout, + .ndo_set_features = cp_set_features, + .ndo_change_mtu = cp_change_mtu, ++ .ndo_features_check = cp_features_check, + + #ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = cp_poll_controller, +@@ -1983,12 +1999,12 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) + dev->ethtool_ops = &cp_ethtool_ops; + dev->watchdog_timeo = TX_TIMEOUT; + +- dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; ++ dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | ++ NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; + + if (pci_using_dac) + dev->features |= NETIF_F_HIGHDMA; + +- /* disabled by default until verified */ + dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; + dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | |