diff mbox

[RFC,09/11] IB/IPoIB: Modify ipoib_get_net_dev_by_params to lookup gid table

Message ID 1474652674-13110-10-git-send-email-ira.weiny@intel.com (mailing list archive)
State RFC
Headers show

Commit Message

Ira Weiny Sept. 23, 2016, 5:44 p.m. UTC
From: Dasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com>

ipoib_get_net_dev_by_params compares incoming gid with local_gid
which is gid at index 0 of the gid table. OPA devices using larger
LIDs may have a different GID format than whats setup in the local_gid
field. Do a search of the gid table in those cases.

Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Dasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com>
Signed-off-by: Don Hiatt <don.hiatt@intel.com>
---
 drivers/infiniband/ulp/ipoib/ipoib_main.c | 37 +++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 2bcde9822e3a..76da1430b415 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -328,6 +328,40 @@  out:
 	return result;
 }
 
+/* retuns true if the incoming gid is assigned to the IPoIB
+ * netdev interface
+ *
+ * OPA devices may have the incoming GID in the OPA GID
+ * format which might not necessarily be assigned to the
+ * netdev interface. This necessitates searching the GID
+ * table to match this OPA GID.
+ */
+static bool ipoib_check_gid(struct ipoib_dev_priv *priv,
+			    const union ib_gid *gid)
+{
+	bool is_local_gid;
+	struct ib_port_attr attr;
+	union ib_gid port_gid;
+	int i;
+
+	if (!gid)
+		return true;
+
+	is_local_gid = !memcmp(gid, &priv->local_gid, sizeof(*gid));
+
+	if (!rdma_cap_opa_ah(priv->ca, priv->port) || is_local_gid)
+		return is_local_gid;
+
+	if (ib_query_port(priv->ca, priv->port, &attr))
+		return false;
+	for (i = 1; i < attr.gid_tbl_len; i++) {
+		if (ib_query_gid(priv->ca, priv->port, i, &port_gid, NULL))
+			return false;
+		if (!memcmp(gid, &port_gid, sizeof(*gid)))
+			return true;
+	}
+	return false;
+}
 /* returns the number of IPoIB netdevs on top a given ipoib device matching a
  * pkey_index and address, if one exists.
  *
@@ -344,8 +378,7 @@  static int ipoib_match_gid_pkey_addr(struct ipoib_dev_priv *priv,
 	struct net_device *net_dev = NULL;
 	int matches = 0;
 
-	if (priv->pkey_index == pkey_index &&
-	    (!gid || !memcmp(gid, &priv->local_gid, sizeof(*gid)))) {
+	if (priv->pkey_index == pkey_index && ipoib_check_gid(priv, gid)) {
 		if (!addr) {
 			net_dev = ipoib_get_master_net_dev(priv->dev);
 		} else {