Merge branch 'x86-kbuild-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / drivers / infiniband / ulp / ipoib / ipoib_multicast.c
index 425e311..25874fc 100644 (file)
@@ -261,7 +261,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
 
                skb->dev = dev;
 
-               if (!skb->dst || !skb->dst->neighbour) {
+               if (!skb_dst(skb) || !skb_dst(skb)->neighbour) {
                        /* put pseudoheader back on for next time */
                        skb_push(skb, sizeof (struct ipoib_pseudoheader));
                }
@@ -707,10 +707,10 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
 
 out:
        if (mcast && mcast->ah) {
-               if (skb->dst            &&
-                   skb->dst->neighbour &&
-                   !*to_ipoib_neigh(skb->dst->neighbour)) {
-                       struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour,
+               if (skb_dst(skb)                &&
+                   skb_dst(skb)->neighbour &&
+                   !*to_ipoib_neigh(skb_dst(skb)->neighbour)) {
+                       struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour,
                                                                        skb->dev);
 
                        if (neigh) {
@@ -720,7 +720,9 @@ out:
                        }
                }
 
+               spin_unlock_irqrestore(&priv->lock, flags);
                ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
+               return;
        }
 
 unlock:
@@ -758,6 +760,20 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
        }
 }
 
+static int ipoib_mcast_addr_is_valid(const u8 *addr, unsigned int addrlen,
+                                    const u8 *broadcast)
+{
+       if (addrlen != INFINIBAND_ALEN)
+               return 0;
+       /* reserved QPN, prefix, scope */
+       if (memcmp(addr, broadcast, 6))
+               return 0;
+       /* signature lower, pkey */
+       if (memcmp(addr + 7, broadcast + 7, 3))
+               return 0;
+       return 1;
+}
+
 void ipoib_mcast_restart_task(struct work_struct *work)
 {
        struct ipoib_dev_priv *priv =
@@ -791,6 +807,11 @@ void ipoib_mcast_restart_task(struct work_struct *work)
        for (mclist = dev->mc_list; mclist; mclist = mclist->next) {
                union ib_gid mgid;
 
+               if (!ipoib_mcast_addr_is_valid(mclist->dmi_addr,
+                                              mclist->dmi_addrlen,
+                                              dev->broadcast))
+                       continue;
+
                memcpy(mgid.raw, mclist->dmi_addr + 4, sizeof mgid);
 
                mcast = __ipoib_mcast_find(dev, &mgid);