sky2: force receive checksum when using RSS on some hardware (v2)
stephen hemminger [Thu, 7 Jul 2011 13:40:00 +0000 (13:40 +0000)]
Found when reviewing the vendor driver. Apparently some chip versions
require receive checksumming to be enabled in order for RSS to work.

Also, if fix_features has to change some settings; put in message
in log in similar manner to netdev_fix_features.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

drivers/net/sky2.c
drivers/net/sky2.h

index c91513e..3fc8683 100644 (file)
@@ -2996,7 +2996,8 @@ static int __devinit sky2_init(struct sky2_hw *hw)
                hw->flags = SKY2_HW_GIGABIT
                        | SKY2_HW_NEWER_PHY
                        | SKY2_HW_NEW_LE
-                       | SKY2_HW_ADV_POWER_CTL;
+                       | SKY2_HW_ADV_POWER_CTL
+                       | SKY2_HW_RSS_CHKSUM;
 
                /* New transmit checksum */
                if (hw->chip_rev != CHIP_REV_YU_EX_B0)
@@ -3024,7 +3025,7 @@ static int __devinit sky2_init(struct sky2_hw *hw)
 
                /* The workaround for status conflicts VLAN tag detection. */
                if (hw->chip_rev == CHIP_REV_YU_FE2_A0)
-                       hw->flags |= SKY2_HW_VLAN_BROKEN;
+                       hw->flags |= SKY2_HW_VLAN_BROKEN | SKY2_HW_RSS_CHKSUM;
                break;
 
        case CHIP_ID_YUKON_SUPR:
@@ -3033,6 +3034,9 @@ static int __devinit sky2_init(struct sky2_hw *hw)
                        | SKY2_HW_NEW_LE
                        | SKY2_HW_AUTO_TX_SUM
                        | SKY2_HW_ADV_POWER_CTL;
+
+               if (hw->chip_rev == CHIP_REV_YU_SU_A0)
+                       hw->flags |= SKY2_HW_RSS_CHKSUM;
                break;
 
        case CHIP_ID_YUKON_UL_2:
@@ -4176,8 +4180,18 @@ static u32 sky2_fix_features(struct net_device *dev, u32 features)
        /* In order to do Jumbo packets on these chips, need to turn off the
         * transmit store/forward. Therefore checksum offload won't work.
         */
-       if (dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U)
+       if (dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U) {
+               netdev_info(dev, "checksum offload not possible with jumbo frames\n");
                features &= ~(NETIF_F_TSO|NETIF_F_SG|NETIF_F_ALL_CSUM);
+       }
+
+       /* Some hardware requires receive checksum for RSS to work. */
+       if ( (features & NETIF_F_RXHASH) &&
+            !(features & NETIF_F_RXCSUM) &&
+            (sky2->hw->flags & SKY2_HW_RSS_CHKSUM)) {
+               netdev_info(dev, "receive hashing forces receive checksum\n");
+               features |= NETIF_F_RXCSUM;
+       }
 
        return features;
 }
index 318c9ae..030221f 100644 (file)
@@ -2281,6 +2281,7 @@ struct sky2_hw {
 #define SKY2_HW_ADV_POWER_CTL  0x00000080      /* additional PHY power regs */
 #define SKY2_HW_RSS_BROKEN     0x00000100
 #define SKY2_HW_VLAN_BROKEN     0x00000200
+#define SKY2_HW_RSS_CHKSUM     0x00000400      /* RSS requires chksum */
 
        u8                   chip_id;
        u8                   chip_rev;