@@ -352,7 +352,7 @@ struct ipoib_dev_priv {
u32 qkey;
union ib_gid local_gid;
- u16 local_lid;
+ u32 local_lid;
unsigned int admin_mtu;
unsigned int mcast_mtu;
@@ -421,6 +421,8 @@ struct ipoib_path {
struct rb_node rb_node;
struct list_head list;
int valid;
+ u32 dlid;
+ u32 slid;
};
struct ipoib_neigh {
@@ -38,6 +38,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/moduleparam.h>
+#include <rdma/opa_addr.h>
#include "ipoib.h"
@@ -1356,6 +1357,16 @@ static void ipoib_cm_tx_start(struct work_struct *work)
}
memcpy(&pathrec, &p->path->pathrec, sizeof pathrec);
+ if (rdma_cap_opa_ah(priv->ca, priv->port)) {
+ if (p->path->dlid >= be16_to_cpu(IB_MULTICAST_LID_BASE))
+ pathrec.dgid.global.interface_id =
+ OPA_MAKE_ID(p->path->dlid);
+
+ if (p->path->slid >= be16_to_cpu(IB_MULTICAST_LID_BASE))
+ pathrec.sgid.global.interface_id =
+ OPA_MAKE_ID(p->path->slid);
+ }
+
spin_unlock_irqrestore(&priv->lock, flags);
netif_tx_unlock_bh(dev);
@@ -52,6 +52,7 @@
#include <linux/inetdevice.h>
#include <rdma/ib_cache.h>
#include <linux/pci.h>
+#include <rdma/opa_addr.h>
#define DRV_VERSION "1.0.0"
@@ -766,6 +767,31 @@ static void path_rec_completion(int status,
spin_lock_irqsave(&priv->lock, flags);
if (!IS_ERR_OR_NULL(ah)) {
+ /*
+ * Extended LIDs might get programmed into GIDs in the
+ * case of OPA devices. Since we have created the ah
+ * above which would have made use of the lids, now is
+ * a good time to change them back to regular GIDs after
+ * saving the extended LIDs.
+ */
+ if (rdma_cap_opa_ah(priv->ca, priv->port) &&
+ ib_is_opa_gid(&pathrec->sgid)) {
+ path->slid = opa_get_lid_from_gid(&pathrec->sgid);
+ pathrec->sgid = path->pathrec.sgid;
+ } else {
+ path->slid = be16_to_cpu(pathrec->slid);
+ }
+
+ if (rdma_cap_opa_ah(priv->ca, priv->port) &&
+ ib_is_opa_gid(&pathrec->dgid)) {
+ path->dlid = opa_get_lid_from_gid(&pathrec->dgid);
+ pathrec->dgid = path->pathrec.dgid;
+ } else {
+ path->dlid = be16_to_cpu(pathrec->dlid);
+ }
+ ipoib_dbg(priv, "PathRec SGID %pI6 DGID %pI6\n",
+ pathrec->sgid.raw, pathrec->dgid.raw);
+
path->pathrec = *pathrec;
old_ah = path->ah;
@@ -581,7 +581,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
port_attr.state);
return;
}
- priv->local_lid = (u16)port_attr.lid;
+ priv->local_lid = port_attr.lid;
netif_addr_lock_bh(dev);
if (!test_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags)) {
@@ -53,4 +53,16 @@ static inline bool ib_is_opa_gid(union ib_gid *gid)
return ((be64_to_cpu(gid->global.interface_id) >> 40) ==
OPA_SPECIAL_OUI);
}
+
+/**
+ * opa_get_lid_from_gid: Returns the last 32 bits of the gid.
+ * OPA devices use one of the gids in the gid table to also
+ * store the lid.
+ *
+ * @gid: The Global identifier
+ */
+static inline u32 opa_get_lid_from_gid(union ib_gid *gid)
+{
+ return be64_to_cpu(gid->global.interface_id) & 0xFFFFFFFF;
+}
#endif /* OPA_ADDR_H */