|
@@ -3691,13 +3691,24 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth);
|
|
|
static inline bool can_checksum_protocol(netdev_features_t features,
|
|
|
__be16 protocol)
|
|
|
{
|
|
|
- return ((features & NETIF_F_GEN_CSUM) ||
|
|
|
- ((features & NETIF_F_V4_CSUM) &&
|
|
|
- protocol == htons(ETH_P_IP)) ||
|
|
|
- ((features & NETIF_F_V6_CSUM) &&
|
|
|
- protocol == htons(ETH_P_IPV6)) ||
|
|
|
- ((features & NETIF_F_FCOE_CRC) &&
|
|
|
- protocol == htons(ETH_P_FCOE)));
|
|
|
+ if (protocol == htons(ETH_P_FCOE))
|
|
|
+ return !!(features & NETIF_F_FCOE_CRC);
|
|
|
+
|
|
|
+ /* Assume this is an IP checksum (not SCTP CRC) */
|
|
|
+
|
|
|
+ if (features & NETIF_F_HW_CSUM) {
|
|
|
+ /* Can checksum everything */
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (protocol) {
|
|
|
+ case htons(ETH_P_IP):
|
|
|
+ return !!(features & NETIF_F_IP_CSUM);
|
|
|
+ case htons(ETH_P_IPV6):
|
|
|
+ return !!(features & NETIF_F_IPV6_CSUM);
|
|
|
+ default:
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_BUG
|
|
@@ -3762,15 +3773,14 @@ void linkwatch_run_queue(void);
|
|
|
static inline netdev_features_t netdev_intersect_features(netdev_features_t f1,
|
|
|
netdev_features_t f2)
|
|
|
{
|
|
|
- if (f1 & NETIF_F_GEN_CSUM)
|
|
|
- f1 |= (NETIF_F_CSUM_MASK & ~NETIF_F_GEN_CSUM);
|
|
|
- if (f2 & NETIF_F_GEN_CSUM)
|
|
|
- f2 |= (NETIF_F_CSUM_MASK & ~NETIF_F_GEN_CSUM);
|
|
|
- f1 &= f2;
|
|
|
- if (f1 & NETIF_F_GEN_CSUM)
|
|
|
- f1 &= ~(NETIF_F_CSUM_MASK & ~NETIF_F_GEN_CSUM);
|
|
|
+ if ((f1 ^ f2) & NETIF_F_HW_CSUM) {
|
|
|
+ if (f1 & NETIF_F_HW_CSUM)
|
|
|
+ f1 |= (NETIF_F_IP_CSUM|NETIF_F_IP_CSUM);
|
|
|
+ else
|
|
|
+ f2 |= (NETIF_F_IP_CSUM|NETIF_F_IP_CSUM);
|
|
|
+ }
|
|
|
|
|
|
- return f1;
|
|
|
+ return f1 & f2;
|
|
|
}
|
|
|
|
|
|
static inline netdev_features_t netdev_get_wanted_features(
|