net: pch_gbe: convert to hw_features

This also fixes bug in xmit path, where TX checksum offload state was used
instead of skb->ip_summed to decide if the offload was needed.

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/pch_gbe/pch_gbe.h b/drivers/net/pch_gbe/pch_gbe.h
index bf126e7..59fac77 100644
--- a/drivers/net/pch_gbe/pch_gbe.h
+++ b/drivers/net/pch_gbe/pch_gbe.h
@@ -597,8 +597,6 @@
  * @rx_ring:		Pointer of Rx descriptor ring structure
  * @rx_buffer_len:	Receive buffer length
  * @tx_queue_len:	Transmit queue length
- * @rx_csum:		Receive TCP/IP checksum enable/disable
- * @tx_csum:		Transmit TCP/IP checksum enable/disable
  * @have_msi:		PCI MSI mode flag
  */
 
@@ -623,8 +621,6 @@
 	struct pch_gbe_rx_ring *rx_ring;
 	unsigned long rx_buffer_len;
 	unsigned long tx_queue_len;
-	bool rx_csum;
-	bool tx_csum;
 	bool have_msi;
 };
 
diff --git a/drivers/net/pch_gbe/pch_gbe_ethtool.c b/drivers/net/pch_gbe/pch_gbe_ethtool.c
index d2174a4..c35d105 100644
--- a/drivers/net/pch_gbe/pch_gbe_ethtool.c
+++ b/drivers/net/pch_gbe/pch_gbe_ethtool.c
@@ -434,57 +434,6 @@
 }
 
 /**
- * pch_gbe_get_rx_csum - Report whether receive checksums are turned on or off
- * @netdev:  Network interface device structure
- * Returns
- *	true(1):  Checksum On
- *	false(0): Checksum Off
- */
-static u32 pch_gbe_get_rx_csum(struct net_device *netdev)
-{
-	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
-
-	return adapter->rx_csum;
-}
-
-/**
- * pch_gbe_set_rx_csum - Turn receive checksum on or off
- * @netdev:  Network interface device structure
- * @data:    Checksum On[true] or Off[false]
- * Returns
- *	0:			Successful.
- *	Negative value:		Failed.
- */
-static int pch_gbe_set_rx_csum(struct net_device *netdev, u32 data)
-{
-	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
-
-	adapter->rx_csum = data;
-	if ((netif_running(netdev)))
-		pch_gbe_reinit_locked(adapter);
-	else
-		pch_gbe_reset(adapter);
-
-	return 0;
-}
-
-/**
- * pch_gbe_set_tx_csum - Turn transmit checksums on or off
- * @netdev: Network interface device structure
- * @data:   Checksum on[true] or off[false]
- * Returns
- *	0:			Successful.
- *	Negative value:		Failed.
- */
-static int pch_gbe_set_tx_csum(struct net_device *netdev, u32 data)
-{
-	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
-
-	adapter->tx_csum = data;
-	return ethtool_op_set_tx_ipv6_csum(netdev, data);
-}
-
-/**
  * pch_gbe_get_strings - Return a set of strings that describe the requested
  *			 objects
  * @netdev:    Network interface device structure
@@ -554,9 +503,6 @@
 	.set_ringparam = pch_gbe_set_ringparam,
 	.get_pauseparam = pch_gbe_get_pauseparam,
 	.set_pauseparam = pch_gbe_set_pauseparam,
-	.get_rx_csum = pch_gbe_get_rx_csum,
-	.set_rx_csum = pch_gbe_set_rx_csum,
-	.set_tx_csum = pch_gbe_set_tx_csum,
 	.get_strings = pch_gbe_get_strings,
 	.get_ethtool_stats = pch_gbe_get_ethtool_stats,
 	.get_sset_count = pch_gbe_get_sset_count,
diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c
index 2ef2f9c..4cc9872 100644
--- a/drivers/net/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/pch_gbe/pch_gbe_main.c
@@ -656,6 +656,7 @@
  */
 static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter)
 {
+	struct net_device *netdev = adapter->netdev;
 	struct pch_gbe_hw *hw = &adapter->hw;
 	u32 rx_mode, tcpip;
 
@@ -666,7 +667,7 @@
 
 	tcpip = ioread32(&hw->reg->TCPIP_ACC);
 
-	if (adapter->rx_csum) {
+	if (netdev->features & NETIF_F_RXCSUM) {
 		tcpip &= ~PCH_GBE_RX_TCPIPACC_OFF;
 		tcpip |= PCH_GBE_RX_TCPIPACC_EN;
 	} else {
@@ -950,7 +951,7 @@
 	frame_ctrl = 0;
 	if (unlikely(skb->len < PCH_GBE_SHORT_PKT))
 		frame_ctrl |= PCH_GBE_TXD_CTRL_APAD;
-	if (unlikely(!adapter->tx_csum))
+	if (skb->ip_summed == CHECKSUM_NONE)
 		frame_ctrl |= PCH_GBE_TXD_CTRL_TCPIP_ACC_OFF;
 
 	/* Performs checksum processing */
@@ -958,7 +959,7 @@
 	 * It is because the hardware accelerator does not support a checksum,
 	 * when the received data size is less than 64 bytes.
 	 */
-	if ((skb->len < PCH_GBE_SHORT_PKT) && (adapter->tx_csum)) {
+	if (skb->len < PCH_GBE_SHORT_PKT && skb->ip_summed != CHECKSUM_NONE) {
 		frame_ctrl |= PCH_GBE_TXD_CTRL_APAD |
 			      PCH_GBE_TXD_CTRL_TCPIP_ACC_OFF;
 		if (skb->protocol == htons(ETH_P_IP)) {
@@ -1426,7 +1427,7 @@
 			length = (rx_desc->rx_words_eob) - 3;
 
 			/* Decide the data conversion method */
-			if (!adapter->rx_csum) {
+			if (!(netdev->features & NETIF_F_RXCSUM)) {
 				/* [Header:14][payload] */
 				if (NET_IP_ALIGN) {
 					/* Because alignment differs,
@@ -2030,6 +2031,29 @@
 }
 
 /**
+ * pch_gbe_set_features - Reset device after features changed
+ * @netdev:   Network interface device structure
+ * @features:  New features
+ * Returns
+ *	0:		HW state updated successfully
+ */
+static int pch_gbe_set_features(struct net_device *netdev, u32 features)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	u32 changed = features ^ netdev->features;
+
+	if (!(changed & NETIF_F_RXCSUM))
+		return 0;
+
+	if (netif_running(netdev))
+		pch_gbe_reinit_locked(adapter);
+	else
+		pch_gbe_reset(adapter);
+
+	return 0;
+}
+
+/**
  * pch_gbe_ioctl - Controls register through a MII interface
  * @netdev:   Network interface device structure
  * @ifr:      Pointer to ifr structure
@@ -2129,6 +2153,7 @@
 	.ndo_set_mac_address = pch_gbe_set_mac,
 	.ndo_tx_timeout = pch_gbe_tx_timeout,
 	.ndo_change_mtu = pch_gbe_change_mtu,
+	.ndo_set_features = pch_gbe_set_features,
 	.ndo_do_ioctl = pch_gbe_ioctl,
 	.ndo_set_multicast_list = &pch_gbe_set_multi,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2334,7 +2359,9 @@
 	netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD;
 	netif_napi_add(netdev, &adapter->napi,
 		       pch_gbe_napi_poll, PCH_GBE_RX_WEIGHT);
-	netdev->features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_GRO;
+	netdev->hw_features = NETIF_F_RXCSUM |
+		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	netdev->features = netdev->hw_features;
 	pch_gbe_set_ethtool_ops(netdev);
 
 	pch_gbe_mac_load_mac_addr(&adapter->hw);
@@ -2373,11 +2400,6 @@
 
 	pch_gbe_check_options(adapter);
 
-	if (adapter->tx_csum)
-		netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-	else
-		netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-
 	/* initialize the wol settings based on the eeprom settings */
 	adapter->wake_up_evt = PCH_GBE_WL_INIT_SETTING;
 	dev_info(&pdev->dev, "MAC address : %pM\n", netdev->dev_addr);
diff --git a/drivers/net/pch_gbe/pch_gbe_param.c b/drivers/net/pch_gbe/pch_gbe_param.c
index ef0996a..5b5d90a 100644
--- a/drivers/net/pch_gbe/pch_gbe_param.c
+++ b/drivers/net/pch_gbe/pch_gbe_param.c
@@ -426,6 +426,8 @@
 void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
 {
 	struct pch_gbe_hw *hw = &adapter->hw;
+	struct net_device *dev = adapter->netdev;
+	int val;
 
 	{ /* Transmit Descriptor Count */
 		static const struct pch_gbe_option opt = {
@@ -466,9 +468,10 @@
 			.err  = "defaulting to Enabled",
 			.def  = PCH_GBE_DEFAULT_RX_CSUM
 		};
-		adapter->rx_csum = XsumRX;
-		pch_gbe_validate_option((int *)(&adapter->rx_csum),
-					&opt, adapter);
+		val = XsumRX;
+		pch_gbe_validate_option(&val, &opt, adapter);
+		if (!val)
+			dev->features &= ~NETIF_F_RXCSUM;
 	}
 	{ /* Checksum Offload Enable/Disable */
 		static const struct pch_gbe_option opt = {
@@ -477,9 +480,10 @@
 			.err  = "defaulting to Enabled",
 			.def  = PCH_GBE_DEFAULT_TX_CSUM
 		};
-		adapter->tx_csum = XsumTX;
-		pch_gbe_validate_option((int *)(&adapter->tx_csum),
-						&opt, adapter);
+		val = XsumTX;
+		pch_gbe_validate_option(&val, &opt, adapter);
+		if (!val)
+			dev->features &= ~NETIF_F_ALL_CSUM;
 	}
 	{ /* Flow Control */
 		static const struct pch_gbe_option opt = {