aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/realtek/r8169.c71
1 files changed, 37 insertions, 34 deletions
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index be425ad5e824..6b7e21a8da57 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -633,32 +633,6 @@ enum rtl_tx_desc_bit_1 {
633 TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */ 633 TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */
634}; 634};
635 635
636static const struct rtl_tx_desc_info {
637 struct {
638 u32 udp;
639 u32 tcp;
640 } checksum;
641 u16 mss_shift;
642 u16 opts_offset;
643} tx_desc_info [] = {
644 [RTL_TD_0] = {
645 .checksum = {
646 .udp = TD0_IP_CS | TD0_UDP_CS,
647 .tcp = TD0_IP_CS | TD0_TCP_CS
648 },
649 .mss_shift = TD0_MSS_SHIFT,
650 .opts_offset = 0
651 },
652 [RTL_TD_1] = {
653 .checksum = {
654 .udp = TD1_IP_CS | TD1_UDP_CS,
655 .tcp = TD1_IP_CS | TD1_TCP_CS
656 },
657 .mss_shift = TD1_MSS_SHIFT,
658 .opts_offset = 1
659 }
660};
661
662enum rtl_rx_desc_bit { 636enum rtl_rx_desc_bit {
663 /* Rx private */ 637 /* Rx private */
664 PID1 = (1 << 18), /* Protocol ID bit 1/2 */ 638 PID1 = (1 << 18), /* Protocol ID bit 1/2 */
@@ -782,6 +756,7 @@ struct rtl8169_private {
782 unsigned int (*phy_reset_pending)(struct rtl8169_private *tp); 756 unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
783 unsigned int (*link_ok)(void __iomem *); 757 unsigned int (*link_ok)(void __iomem *);
784 int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); 758 int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
759 bool (*tso_csum)(struct rtl8169_private *, struct sk_buff *, u32 *);
785 760
786 struct { 761 struct {
787 DECLARE_BITMAP(flags, RTL_FLAG_MAX); 762 DECLARE_BITMAP(flags, RTL_FLAG_MAX);
@@ -5941,16 +5916,36 @@ static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp, struct sk_buff *skb)
5941 return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34; 5916 return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34;
5942} 5917}
5943 5918
5944static inline bool rtl8169_tso_csum(struct rtl8169_private *tp, 5919static bool rtl8169_tso_csum_v1(struct rtl8169_private *tp,
5945 struct sk_buff *skb, u32 *opts) 5920 struct sk_buff *skb, u32 *opts)
5946{ 5921{
5947 const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
5948 u32 mss = skb_shinfo(skb)->gso_size; 5922 u32 mss = skb_shinfo(skb)->gso_size;
5949 int offset = info->opts_offset;
5950 5923
5951 if (mss) { 5924 if (mss) {
5952 opts[0] |= TD_LSO; 5925 opts[0] |= TD_LSO;
5953 opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift; 5926 opts[0] |= min(mss, TD_MSS_MAX) << TD0_MSS_SHIFT;
5927 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
5928 const struct iphdr *ip = ip_hdr(skb);
5929
5930 if (ip->protocol == IPPROTO_TCP)
5931 opts[0] |= TD0_IP_CS | TD0_TCP_CS;
5932 else if (ip->protocol == IPPROTO_UDP)
5933 opts[0] |= TD0_IP_CS | TD0_UDP_CS;
5934 else
5935 WARN_ON_ONCE(1);
5936 }
5937
5938 return true;
5939}
5940
5941static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
5942 struct sk_buff *skb, u32 *opts)
5943{
5944 u32 mss = skb_shinfo(skb)->gso_size;
5945
5946 if (mss) {
5947 opts[0] |= TD_LSO;
5948 opts[1] |= min(mss, TD_MSS_MAX) << TD1_MSS_SHIFT;
5954 } else if (skb->ip_summed == CHECKSUM_PARTIAL) { 5949 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
5955 const struct iphdr *ip = ip_hdr(skb); 5950 const struct iphdr *ip = ip_hdr(skb);
5956 5951
@@ -5958,15 +5953,16 @@ static inline bool rtl8169_tso_csum(struct rtl8169_private *tp,
5958 return skb_checksum_help(skb) == 0 && rtl_skb_pad(skb); 5953 return skb_checksum_help(skb) == 0 && rtl_skb_pad(skb);
5959 5954
5960 if (ip->protocol == IPPROTO_TCP) 5955 if (ip->protocol == IPPROTO_TCP)
5961 opts[offset] |= info->checksum.tcp; 5956 opts[1] |= TD1_IP_CS | TD1_TCP_CS;
5962 else if (ip->protocol == IPPROTO_UDP) 5957 else if (ip->protocol == IPPROTO_UDP)
5963 opts[offset] |= info->checksum.udp; 5958 opts[1] |= TD1_IP_CS | TD1_UDP_CS;
5964 else 5959 else
5965 WARN_ON_ONCE(1); 5960 WARN_ON_ONCE(1);
5966 } else { 5961 } else {
5967 if (unlikely(rtl_test_hw_pad_bug(tp, skb))) 5962 if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
5968 return rtl_skb_pad(skb); 5963 return rtl_skb_pad(skb);
5969 } 5964 }
5965
5970 return true; 5966 return true;
5971} 5967}
5972 5968
@@ -5994,7 +5990,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
5994 opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb)); 5990 opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
5995 opts[0] = DescOwn; 5991 opts[0] = DescOwn;
5996 5992
5997 if (!rtl8169_tso_csum(tp, skb, opts)) 5993 if (!tp->tso_csum(tp, skb, opts))
5998 goto err_update_stats; 5994 goto err_update_stats;
5999 5995
6000 len = skb_headlen(skb); 5996 len = skb_headlen(skb);
@@ -7145,6 +7141,13 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
7145 /* 8110SCd requires hardware Rx VLAN - disallow toggling */ 7141 /* 8110SCd requires hardware Rx VLAN - disallow toggling */
7146 dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX; 7142 dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
7147 7143
7144 if (tp->txd_version == RTL_TD_0)
7145 tp->tso_csum = rtl8169_tso_csum_v1;
7146 else if (tp->txd_version == RTL_TD_1)
7147 tp->tso_csum = rtl8169_tso_csum_v2;
7148 else
7149 WARN_ON_ONCE(1);
7150
7148 dev->hw_features |= NETIF_F_RXALL; 7151 dev->hw_features |= NETIF_F_RXALL;
7149 dev->hw_features |= NETIF_F_RXFCS; 7152 dev->hw_features |= NETIF_F_RXFCS;
7150 7153