Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[cascardo/linux.git] / net / core / datagram.c
index 6b1c04c..488dd1a 100644 (file)
@@ -739,22 +739,38 @@ __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len)
        __sum16 sum;
 
        sum = csum_fold(skb_checksum(skb, 0, len, skb->csum));
-       if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) && !sum &&
-           !skb->csum_complete_sw)
-               netdev_rx_csum_fault(skb->dev);
-
-       /* Save checksum complete for later use */
-       skb->csum = sum;
-       skb->ip_summed = CHECKSUM_COMPLETE;
-       skb->csum_complete_sw = 1;
-
+       if (likely(!sum)) {
+               if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
+                   !skb->csum_complete_sw)
+                       netdev_rx_csum_fault(skb->dev);
+       }
+       skb->csum_valid = !sum;
        return sum;
 }
 EXPORT_SYMBOL(__skb_checksum_complete_head);
 
 __sum16 __skb_checksum_complete(struct sk_buff *skb)
 {
-       return __skb_checksum_complete_head(skb, skb->len);
+       __wsum csum;
+       __sum16 sum;
+
+       csum = skb_checksum(skb, 0, skb->len, 0);
+
+       /* skb->csum holds pseudo checksum */
+       sum = csum_fold(csum_add(skb->csum, csum));
+       if (likely(!sum)) {
+               if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
+                   !skb->csum_complete_sw)
+                       netdev_rx_csum_fault(skb->dev);
+       }
+
+       /* Save full packet checksum */
+       skb->csum = csum;
+       skb->ip_summed = CHECKSUM_COMPLETE;
+       skb->csum_complete_sw = 1;
+       skb->csum_valid = !sum;
+
+       return sum;
 }
 EXPORT_SYMBOL(__skb_checksum_complete);