Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[sfrench/cifs-2.6.git] / net / core / netpoll.c
index 5265dfd699284a960c5fd95b33a6daf722b1a0bc..49424a42a2c0385b2924510a11ff89dfdfcfcf2f 100644 (file)
@@ -101,16 +101,20 @@ void netpoll_queue(struct sk_buff *skb)
 static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
                             unsigned short ulen, u32 saddr, u32 daddr)
 {
-       if (uh->check == 0)
+       unsigned int psum;
+
+       if (uh->check == 0 || skb->ip_summed == CHECKSUM_UNNECESSARY)
                return 0;
 
-       if (skb->ip_summed == CHECKSUM_HW)
-               return csum_tcpudp_magic(
-                       saddr, daddr, ulen, IPPROTO_UDP, skb->csum);
+       psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
+
+       if (skb->ip_summed == CHECKSUM_HW &&
+           !(u16)csum_fold(csum_add(psum, skb->csum)))
+               return 0;
 
-       skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
+       skb->csum = psum;
 
-       return csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
+       return __skb_checksum_complete(skb);
 }
 
 /*
@@ -489,7 +493,7 @@ int __netpoll_rx(struct sk_buff *skb)
 
        if (ulen != len)
                goto out;
-       if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr) < 0)
+       if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr))
                goto out;
        if (np->local_ip && np->local_ip != ntohl(iph->daddr))
                goto out;
@@ -703,7 +707,7 @@ int netpoll_setup(struct netpoll *np)
 
        if (!np->local_ip) {
                rcu_read_lock();
-               in_dev = __in_dev_get(ndev);
+               in_dev = __in_dev_get_rcu(ndev);
 
                if (!in_dev || !in_dev->ifa_list) {
                        rcu_read_unlock();