IB/mlx4: Handle protocol field in multicast table
authorAleksey Senin <alex@senin.name>
Thu, 2 Dec 2010 11:44:49 +0000 (11:44 +0000)
committerRoland Dreier <rolandd@cisco.com>
Wed, 12 Jan 2011 22:49:17 +0000 (14:49 -0800)
The newest device firmware stores IB vs. Ethernet protocol in two bits
in members_count field of multicast group table (0: Infiniband, 1:
Ethernet).  When changing the QP members count for a multicast group,
it important not to reset this information.  When calling multicast
attach first time, the protocol type should be specified.  In this
patch we always set it IB, but in the future we will handle Ethernet
too.  When looking for a QP, the protocol type shoud be checked too.

Signed-off-by: Aleksey Senin <alekseys@voltaire.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/mlx4/main.c
drivers/net/mlx4/mcg.c
include/linux/mlx4/device.h
include/linux/mlx4/driver.h

index d68d849ab866e9041beb907b287084bdf7cabc74..c7a6213c6996df1202f9b42b4011a348f992fbb3 100644 (file)
@@ -623,8 +623,9 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
        struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
        struct mlx4_ib_qp *mqp = to_mqp(ibqp);
 
-       err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, !!(mqp->flags &
-                                   MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK));
+       err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw,
+                                   !!(mqp->flags & MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK),
+                                   MLX4_PROTOCOL_IB);
        if (err)
                return err;
 
@@ -635,7 +636,7 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
        return 0;
 
 err_add:
-       mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw);
+       mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, MLX4_PROTOCOL_IB);
        return err;
 }
 
@@ -665,7 +666,7 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
        struct mlx4_ib_gid_entry *ge;
 
        err = mlx4_multicast_detach(mdev->dev,
-                                   &mqp->mqp, gid->raw);
+                                   &mqp->mqp, gid->raw, MLX4_PROTOCOL_IB);
        if (err)
                return err;
 
index c4f88b7ef7b6dbc33a4d6d08bb2bca1b9a010ff3..79cf42db2ea9ad504341023d05ed85d121377e8d 100644 (file)
@@ -95,7 +95,8 @@ static int mlx4_MGID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox
  * entry in hash chain and *mgm holds end of hash chain.
  */
 static int find_mgm(struct mlx4_dev *dev,
-                   u8 *gid, struct mlx4_cmd_mailbox *mgm_mailbox,
+                   u8 *gid, enum mlx4_protocol protocol,
+                   struct mlx4_cmd_mailbox *mgm_mailbox,
                    u16 *hash, int *prev, int *index)
 {
        struct mlx4_cmd_mailbox *mailbox;
@@ -134,7 +135,8 @@ static int find_mgm(struct mlx4_dev *dev,
                        return err;
                }
 
-               if (!memcmp(mgm->gid, gid, 16))
+               if (!memcmp(mgm->gid, gid, 16) &&
+                   be32_to_cpu(mgm->members_count) >> 30 == protocol)
                        return err;
 
                *prev = *index;
@@ -146,7 +148,7 @@ static int find_mgm(struct mlx4_dev *dev,
 }
 
 int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
-                         int block_mcast_loopback)
+                         int block_mcast_loopback, enum mlx4_protocol protocol)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
        struct mlx4_cmd_mailbox *mailbox;
@@ -165,7 +167,7 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
 
        mutex_lock(&priv->mcg_table.mutex);
 
-       err = find_mgm(dev, gid, mailbox, &hash, &prev, &index);
+       err = find_mgm(dev, gid, protocol, mailbox, &hash, &prev, &index);
        if (err)
                goto out;
 
@@ -187,7 +189,7 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
                memcpy(mgm->gid, gid, 16);
        }
 
-       members_count = be32_to_cpu(mgm->members_count);
+       members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
        if (members_count == MLX4_QP_PER_MGM) {
                mlx4_err(dev, "MGM at index %x is full.\n", index);
                err = -ENOMEM;
@@ -207,7 +209,7 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
        else
                mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK);
 
-       mgm->members_count       = cpu_to_be32(members_count);
+       mgm->members_count = cpu_to_be32(members_count | (u32) protocol << 30);
 
        err = mlx4_WRITE_MCG(dev, index, mailbox);
        if (err)
@@ -242,7 +244,8 @@ out:
 }
 EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
 
-int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
+int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+                         enum mlx4_protocol protocol)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
        struct mlx4_cmd_mailbox *mailbox;
@@ -260,7 +263,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
 
        mutex_lock(&priv->mcg_table.mutex);
 
-       err = find_mgm(dev, gid, mailbox, &hash, &prev, &index);
+       err = find_mgm(dev, gid, protocol, mailbox, &hash, &prev, &index);
        if (err)
                goto out;
 
@@ -270,7 +273,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
                goto out;
        }
 
-       members_count = be32_to_cpu(mgm->members_count);
+       members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
        for (loc = -1, i = 0; i < members_count; ++i)
                if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn)
                        loc = i;
@@ -282,7 +285,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
        }
 
 
-       mgm->members_count = cpu_to_be32(--members_count);
+       mgm->members_count = cpu_to_be32(--members_count | (u32) protocol << 30);
        mgm->qp[loc]       = mgm->qp[i - 1];
        mgm->qp[i - 1]     = 0;
 
index a7b15bc7648e27744fea2fee5de8cefb83f99340..0492146420365ce1b0f2cefa6c2e0ef8d0abb8d4 100644 (file)
@@ -144,6 +144,11 @@ enum {
        MLX4_STAT_RATE_OFFSET   = 5
 };
 
+enum mlx4_protocol {
+       MLX4_PROTOCOL_IB,
+       MLX4_PROTOCOL_EN,
+};
+
 enum {
        MLX4_MTT_FLAG_PRESENT           = 1
 };
@@ -500,8 +505,9 @@ int mlx4_INIT_PORT(struct mlx4_dev *dev, int port);
 int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port);
 
 int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
-                         int block_mcast_loopback);
-int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]);
+                         int block_mcast_loopback, enum mlx4_protocol protocol);
+int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+                         enum mlx4_protocol protocol);
 
 int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index);
 void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index);
index f407cd4bfb341d7a2ac0a6f624130fa8430f6d51..e1eebf78caba1232eabc2a515e33a17513cfd12d 100644 (file)
@@ -34,6 +34,7 @@
 #define MLX4_DRIVER_H
 
 #include <linux/device.h>
+#include <linux/mlx4/device.h>
 
 struct mlx4_dev;
 
@@ -44,11 +45,6 @@ enum mlx4_dev_event {
        MLX4_DEV_EVENT_PORT_REINIT,
 };
 
-enum mlx4_protocol {
-       MLX4_PROTOCOL_IB,
-       MLX4_PROTOCOL_EN,
-};
-
 struct mlx4_interface {
        void *                  (*add)   (struct mlx4_dev *dev);
        void                    (*remove)(struct mlx4_dev *dev, void *context);