* @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
*/
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;
};
}
/**
- * 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
.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,
*/
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;
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 {
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 */
* 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)) {
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,
}
/**
+ * 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
.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
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);
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);
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 = {
.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 = {
.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 = {