Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e64e0c89 authored by Heiner Kallweit's avatar Heiner Kallweit Committed by David S. Miller
Browse files

r8169: implement callback ndo_features_check



Implement callback ndo_features_check and move all feature checks there.
This will allow us to get rid of r8169_csum_workaround() completely in
a subsequent step. Like in the vendor driver disable HW csum for short
packets on RTL8168b.

Signed-off-by: default avatarHeiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0170d594
Loading
Loading
Loading
Loading
+36 −24
Original line number Original line Diff line number Diff line
@@ -539,11 +539,11 @@ enum rtl_tx_desc_bit_1 {
	TD1_GTSENV4	= (1 << 26),		/* Giant Send for IPv4 */
	TD1_GTSENV4	= (1 << 26),		/* Giant Send for IPv4 */
	TD1_GTSENV6	= (1 << 25),		/* Giant Send for IPv6 */
	TD1_GTSENV6	= (1 << 25),		/* Giant Send for IPv6 */
#define GTTCPHO_SHIFT			18
#define GTTCPHO_SHIFT			18
#define GTTCPHO_MAX			0x7fU
#define GTTCPHO_MAX			0x7f


	/* Second doubleword. */
	/* Second doubleword. */
#define TCPHO_SHIFT			18
#define TCPHO_SHIFT			18
#define TCPHO_MAX			0x3ffU
#define TCPHO_MAX			0x3ff
#define TD1_MSS_SHIFT			18	/* MSS position (11 bits) */
#define TD1_MSS_SHIFT			18	/* MSS position (11 bits) */
	TD1_IPv6_CS	= (1 << 28),		/* Calculate IPv6 checksum */
	TD1_IPv6_CS	= (1 << 28),		/* Calculate IPv6 checksum */
	TD1_IPv4_CS	= (1 << 29),		/* Calculate IPv4 checksum */
	TD1_IPv4_CS	= (1 << 29),		/* Calculate IPv4 checksum */
@@ -5534,11 +5534,6 @@ static void r8169_csum_workaround(struct rtl8169_private *tp,
		} while (segs);
		} while (segs);


		dev_consume_skb_any(skb);
		dev_consume_skb_any(skb);
	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
		if (skb_checksum_help(skb) < 0)
			goto drop;

		rtl8169_start_xmit(skb, tp->dev);
	} else {
	} else {
drop:
drop:
		tp->dev->stats.tx_dropped++;
		tp->dev->stats.tx_dropped++;
@@ -5595,13 +5590,6 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
	u32 mss = skb_shinfo(skb)->gso_size;
	u32 mss = skb_shinfo(skb)->gso_size;


	if (mss) {
	if (mss) {
		if (transport_offset > GTTCPHO_MAX) {
			netif_warn(tp, tx_err, tp->dev,
				   "Invalid transport offset 0x%x for TSO\n",
				   transport_offset);
			return false;
		}

		switch (vlan_get_protocol(skb)) {
		switch (vlan_get_protocol(skb)) {
		case htons(ETH_P_IP):
		case htons(ETH_P_IP):
			opts[0] |= TD1_GTSENV4;
			opts[0] |= TD1_GTSENV4;
@@ -5624,16 +5612,6 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
		u8 ip_protocol;
		u8 ip_protocol;


		if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
			return !(skb_checksum_help(skb) || eth_skb_pad(skb));

		if (transport_offset > TCPHO_MAX) {
			netif_warn(tp, tx_err, tp->dev,
				   "Invalid transport offset 0x%x\n",
				   transport_offset);
			return false;
		}

		switch (vlan_get_protocol(skb)) {
		switch (vlan_get_protocol(skb)) {
		case htons(ETH_P_IP):
		case htons(ETH_P_IP):
			opts[1] |= TD1_IPv4_CS;
			opts[1] |= TD1_IPv4_CS;
@@ -5790,6 +5768,39 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
	return NETDEV_TX_BUSY;
	return NETDEV_TX_BUSY;
}
}


static netdev_features_t rtl8169_features_check(struct sk_buff *skb,
						struct net_device *dev,
						netdev_features_t features)
{
	int transport_offset = skb_transport_offset(skb);
	struct rtl8169_private *tp = netdev_priv(dev);

	if (skb_is_gso(skb)) {
		if (transport_offset > GTTCPHO_MAX &&
		    rtl_chip_supports_csum_v2(tp))
			features &= ~NETIF_F_ALL_TSO;
	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
		if (skb->len < ETH_ZLEN) {
			switch (tp->mac_version) {
			case RTL_GIGA_MAC_VER_11:
			case RTL_GIGA_MAC_VER_12:
			case RTL_GIGA_MAC_VER_17:
			case RTL_GIGA_MAC_VER_34:
				features &= ~NETIF_F_CSUM_MASK;
				break;
			default:
				break;
			}
		}

		if (transport_offset > TCPHO_MAX &&
		    rtl_chip_supports_csum_v2(tp))
			features &= ~NETIF_F_CSUM_MASK;
	}

	return vlan_features_check(skb, features);
}

static void rtl8169_pcierr_interrupt(struct net_device *dev)
static void rtl8169_pcierr_interrupt(struct net_device *dev)
{
{
	struct rtl8169_private *tp = netdev_priv(dev);
	struct rtl8169_private *tp = netdev_priv(dev);
@@ -6546,6 +6557,7 @@ static const struct net_device_ops rtl_netdev_ops = {
	.ndo_stop		= rtl8169_close,
	.ndo_stop		= rtl8169_close,
	.ndo_get_stats64	= rtl8169_get_stats64,
	.ndo_get_stats64	= rtl8169_get_stats64,
	.ndo_start_xmit		= rtl8169_start_xmit,
	.ndo_start_xmit		= rtl8169_start_xmit,
	.ndo_features_check	= rtl8169_features_check,
	.ndo_tx_timeout		= rtl8169_tx_timeout,
	.ndo_tx_timeout		= rtl8169_tx_timeout,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_change_mtu		= rtl8169_change_mtu,
	.ndo_change_mtu		= rtl8169_change_mtu,